We have collected a complex amount of information about the food environments within the three locations: Accra and Ho in Ghana, and Nairobi in Kenya. The following document will use Latent Class Analysis to characterise each food environment. First, let’s load the data and then we will analyse each context separately.
# Set up
set.seed(281190)
library(poLCA)
library(data.table)
library(ggplot2)
# Load and tidy data
# Ghana
source("./tidy_gis_data_ghana.R")
ghana <- as.data.table(outlets)
# poLCA requires only positive values i.e. 1/2 not 0/1 - so add 1 onto everything!
ghana[,c(15:40,51:76,96:111)]<- ghana[,c(15:40,51:76,96:111)] + 1
#Kenya
source("./tidy_gis_data_kenya.R")
nairobi <- as.data.table(outlets)
rm(outlets)
nairobi[,c(23:48,51:56,58:82,93:103)] <- nairobi[,c(23:48,51:56,58:82,93:103)] + 1
nairobi$outlet_type[nairobi$outlet_type == 9] <- 7 # Recode to help LCA process (else will estimate all parameter values in between)
nairobi$outlet_type[nairobi$outlet_type == 96] <- 8
Nairbo, Kenya
We will start with the data for Nairobi. I have run the analysis for as much data as we have that is directly comparable to the Ghana data to aid interpretation. This includes:
- Outlet type - what the outlet was, hether it contains an advertisement and what type of advert it was
- Foods sold - split by type of food e.g. grains/cereals, fressh meat & poultry, fruit etc
- Foods being advertised - by same food categories as above
One issue is that we are estimating a lot of parameters here (due to large amount of variables). Should we look to reduce the number of variables (i.e. using PCA) then cluster them first? For now I have not done this but simply run the LCA by itself.
We want to find the ‘best’ number of latent classes that describes the data well. An increasing number of clusters will likely always produce a better fitting model (on some metrics), however also brings added complexity through a larger number of groups. What we want to achieve is a parsimonious solution that maximises the model fit, but minimises the number of groups. To do this, we will run the LCA for a range of solutions between 1 and 10 (I am hypothesising that more than 10 classes is not useful). We will then compare model fit between these solutions. What we are looking for is the point where additional groups in the model produces little additional model benefit - this is refered to as the ‘knee point’. I have done this for 4 common metrics in LCA research:
- Akaike Information Criterion (AIC)
- Bayesian Information Criterion (BIC)
- G-squared statistic
- Chi-squared test statistic
Smaller values for each metric represent a better fitting model.
# Define variables to be used in LCA to estimate groups (too many variables?)
f <- with(nairobi,
cbind(# Type of outlet
outlet_w_advert, outlet_no_advert, advert_only, supermarket, shop, kiosk, stand_table_top, local_vendor, restaurant, bar_pub, other_outlet, billboard_adv, poster_adv, onsite_adv, painting_adv,
# Foods sold
grain_cereal, fresh_meat_poultry, fresh_fish_shellfish, procssd_fried_meat_poultry, procssd_fried_fish, trad_mixed_dishes, modern_mixed_dishes, soups_stews, fried_roots_tubers_plntn_pots, nonfried_roots_tubers_plntn_pots, fruits, vegetables, cakes_sweets, savoury_snacks_pies, sodas_sweetened_bevs, milk, fresh_juices, alcohol, sugar_sweet_spreads, tea_coffee, fats_oils, nuts_seeds, legumes_pulses, condiments, eggs, other,
# Advertisements (fresh juices missing)
adv_grain_cereal, adv_fresh_meat_poultry, adv_fresh_fish_shellfish, adv_procssd_fried_meat_poultry, adv_procssd_fried_fish, adv_trad_mixed_dishes, adv_modern_mixed_dishes, adv_soups_stews, adv_fried_roots_tubers_plntn_pots, adv_nonfried_roots_tubers_plntn_pots, adv_fruits, adv_vegetables, adv_cakes_sweets, adv_savoury_snacks_pies, adv_sodas_sweetened_bevs, adv_milk, adv_alcohol, adv_sugar_sweet_spreads, adv_tea_coffee, adv_fats_oils, adv_nuts_seeds, adv_legumes_pulses, adv_condiments, adv_eggs, adv_other)~1)
# Identify best number of groups
numbers <- c(1:10)
for (i in numbers) {
temp <- poLCA(f, nairobi, nclass=i, nrep=20, maxiter=100000, verbose=FALSE, na.rm=T)
assign(paste0("lca_all",i), temp)
rm(temp)
}
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
# Compare solutions
AIC <- c(rbind(lca_all1$aic, lca_all2$aic, lca_all3$aic, lca_all4$aic, lca_all5$aic,
lca_all6$aic, lca_all7$aic, lca_all8$aic, lca_all9$aic, lca_all10$aic))
BIC <- c(rbind(lca_all1$bic, lca_all2$bic, lca_all3$bic, lca_all4$bic, lca_all5$bic,
lca_all6$bic, lca_all7$bic, lca_all8$bic, lca_all9$bic, lca_all10$bic))
Gsq <- c(rbind(lca_all1$Gsq, lca_all2$Gsq, lca_all3$Gsq, lca_all4$Gsq, lca_all5$Gsq,
lca_all6$Gsq, lca_all7$Gsq, lca_all8$Gsq, lca_all9$Gsq, lca_all10$Gsq))
Chisq <- c(rbind(lca_all1$Chisq, lca_all2$Chisq, lca_all3$Chisq, lca_all4$Chisq, lca_all5$Chisq,
lca_all6$Chisq, lca_all7$Chisq, lca_all8$Chisq, lca_all9$Chisq, lca_all10$Chisq))
Groups <- c(1:10)
numb_grps_all <- cbind(Groups,AIC,BIC,Gsq,Chisq) # Put together in one table
write.table(numb_grps_all, "number_of_groups_nairobi.txt", sep = "\t", row.names = FALSE) # Save
# Plot values
numb_grps_all <- as.data.frame(numb_grps_all)
plot1 <- ggplot(numb_grps_all, aes(x = Groups, y = AIC)) + geom_point() + xlab("Number of classes") + ylab("Akaike Information Criterion") + scale_x_continuous(limits=c(0, 10), breaks = seq(0,10,2))
ggsave("./Plots/nairobi_lca_aic.tiff", plot = plot1, dpi = 300, width = 7, height = 7)
ggsave("./Plots low res/nairobi_lca_aic.jpeg", plot = plot1, dpi = 300, width = 7, height = 7)
plot1
plot2 <- ggplot(numb_grps_all, aes(x = Groups, y = BIC)) + geom_point() + xlab("Number of classes") + ylab("Bayesian Information Criterion") + scale_x_continuous(limits=c(0, 10), breaks = seq(0,10,2))
ggsave("./Plots/nairobi_lca_bic.tiff", plot = plot2, dpi = 300, width = 7, height = 7)
ggsave("./Plots low res/nairobi_lca_bic.jpeg", plot = plot2, dpi = 300, width = 7, height = 7)

plot2
plot3 <- ggplot(numb_grps_all, aes(x = Groups, y = Gsq)) + geom_point() + xlab("Number of classes") + ylab("G-squared statistic") + scale_x_continuous(limits=c(0, 10), breaks = seq(0,10,2))
ggsave("./Plots/nairobi_lca_gsq.tiff", plot = plot3, dpi = 300, width = 7, height = 7)
ggsave("./Plots low res/nairobi_lca_bic.jpeg", plot = plot3, dpi = 300, width = 7, height = 7)

plot3
plot4 <- ggplot(numb_grps_all, aes(x = Groups, y = Chisq)) + geom_point() + xlab("Number of classes") + ylab("Chi-squared statistic") + scale_x_continuous(limits=c(0, 10), breaks = seq(0,10,2))
ggsave("./Plots/nairobi_lca_chisq.tiff", plot = plot4, dpi = 300, width = 7, height = 7)
ggsave("./Plots low res/nairobi_lca_chisq.jpeg", plot = plot4, dpi = 300, width = 7, height = 7)

plot4

The models suggest the following:
- AIC - An increasing number of groups produces better fitting models, but with diminishing returns. At 5 groups, the improvements stay relatively flat suggesting that they are not adding much to the solution.
- BIC - We broadly see an improving solution upto 5 classes, whereby model performance gets worse with additional groups.
- G-squared statistics - an increasing number of groups produces better fitting models, but there is no clear knee point like with the AIC. Relative improvements slow down after 5 classes.
- Chi-squared statistic - Any model that is not a 1 class model is a marked improvement.
Based on these metrics, a 5 class solution was selected as the final model. I have included the model summary below. It includes the conditional probabilities of each class (i.e. their mean characteristics of each input variable) and their class prevalence (i.e. how big they are). Also included is the whole sample average characteristics to aid interpretation.
source("./tidy_poLCA_results.R") # For 5 class solution, if change number of classes then need to manually edit
write.csv(results, "./cond_prob_nairobi.csv") # Save
results
Ok let’s have a look at the conditional probabilities by data category.
Outlet Type
library(ggplot2)
library(grid)
# Reshape the results table into format for ggplot
library(reshape2)
hold <- results[4:11,] # Take only outlet variables
temp <- melt((hold), na.rm=TRUE) # Turn into long format
# Polar plot
nairobi_lca1 <- ggplot(temp, aes(x=Value, y=value, group = variable, colour=variable)) +
geom_line(size=1.2) + ylim(0,1) +
coord_polar() + labs(x = NULL, y = NULL, color = "Latent Class") + theme(axis.text.x = element_text(angle = 0, hjust = 1.5, size = 10)) +
theme(legend.position="bottom") + ggtitle("Outlet Types") + theme(plot.title = element_text(hjust = 0.5)) + scale_color_brewer(palette="Set3") + theme(axis.text.y=element_blank(), axis.ticks.y=element_blank()) + theme(plot.margin=unit(c(0.5,2,0.5,2),"cm")) + scale_x_discrete(labels = c("bar_pub" = "bar/pub", "local_vendor" = "local vendor", "stand_table_top" = "tabletop", "other_outlet" = "other"))
nairobi_lca1_noleg <- nairobi_lca1 + theme(legend.position = "none") # Plot without legend
# Plot but have names overlap
gt_1 <- ggplot_gtable(ggplot_build(nairobi_lca1)) # With legend
gt_1$layout$clip[gt_1$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_outlet_type_nairobi.tiff", plot = gt_1, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_outlet_type_nairobi.jpeg", plot = gt_1, dpi = 300, scale = 1)
plot(gt_1)


gt_1_nl <- ggplot_gtable(ggplot_build(nairobi_lca1_noleg)) # Without legend
gt_1_nl$layout$clip[gt_1_nl$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_outlet_type_nairobi_noleg.tiff", plot = gt_1_nl, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_outlet_type_nairobi_noleg.jpeg", plot = gt_1_nl, dpi = 300, scale = 1)
# Function to store legend
get_legend<-function(myggplot){
tmp <- ggplot_gtable(ggplot_build(myggplot))
leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
legend <- tmp$grobs[[leg]]
return(legend)
}
legend <- get_legend(nairobi_lca1) # Store legend
Advert Type
library(ggplot2)
library(grid)
# Reshape the results table into format for ggplot
library(reshape2)
hold <- results[c(1:3, 12:15),] # Take only outlet variables
temp <- melt((hold), na.rm=TRUE) # Turn into long format
# Polar plot
nairobi_lca1a <- ggplot(temp, aes(x=Value, y=value, group = variable, colour=variable)) +
geom_line(size=1.2) + ylim(0,1) +
coord_polar() + labs(x = NULL, y = NULL, color = "Latent Class") + theme(axis.text.x = element_text(angle = 0, hjust = 1.5, size = 10)) +
theme(legend.position="bottom") + ggtitle("Advert Types") + theme(plot.title = element_text(hjust = 0.5)) + scale_color_brewer(palette="Set3") + theme(axis.text.y=element_blank(), axis.ticks.y=element_blank()) + theme(plot.margin=unit(c(0.5,2,0.5,2),"cm")) + scale_x_discrete(labels = c("billboard_adv" = "billboard advert", "onsite_adv" = "onsite advert", "poster_adv" = "poster advert", "outlet_no_advert" = "outlet no advert", "outlet_w_advert"= "outlet with advert", "painting_adv" = "painting", "advert_only" = "advert"))
nairobi_lca1_nolega <- nairobi_lca1a + theme(legend.position = "none") # Plot without legend
# Plot but have names overlap
gt_1a <- ggplot_gtable(ggplot_build(nairobi_lca1a)) # With legend
gt_1a$layout$clip[gt_1a$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_advert_type_nairobi.tiff", plot = gt_1a, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_advert_type_nairobi.jpeg", plot = gt_1a, dpi = 300, scale = 1)
plot(gt_1a)


gt_1_nla <- ggplot_gtable(ggplot_build(nairobi_lca1_nolega)) # Without legend
gt_1_nla$layout$clip[gt_1_nla$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_advert_type_nairobi_noleg.tiff", plot = gt_1_nla, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_advert_type_nairobi_noleg.jpeg", plot = gt_1_nla, dpi = 300, scale = 1)
Food being sold
# Reshape the results table into format for ggplot
hold <- results[16:41,] # Take only outlet variables
temp <- melt((hold), na.rm=TRUE) # Turn into long format
# Polar plot
nairobi_lca2 <- ggplot(temp, aes(x=Value, y=value, group = variable, colour=variable)) +
geom_line(size=1.2) + ylim(0,1) +
coord_polar() + labs(x = NULL, y = NULL, color = "Latent Class") + theme(axis.text.x = element_text(angle = 0, hjust = 1.5, size = 10)) +
theme(legend.position="bottom") + ggtitle("Food Sold") + theme(plot.title = element_text(hjust = 0.5)) + scale_color_brewer(palette="Set3") + theme(axis.text.y=element_blank(), axis.ticks.y=element_blank()) + theme(plot.margin=unit(c(0.5,2,0.5,2),"cm")) + scale_x_discrete(labels = c("fats_oils" = "fats/oils", "fresh_fish_shellfish" = "fresh fish", "cakes_sweets" = "cakes/sweets", "fresh_meat_poultry" = "fresh meat", "fried_roots_tubers_plntn_pots" = "fried root veg.", "grain_cereal" = "grain/cereal", "legumes_pulses" = "legumes/pulses", "modern_mixed_dishes" = "m.dish", "nuts_seeds"= "nuts/seeds", "procssd_fried_fish" = "processed fish", "procssd_fried_meat_poultry" = "processed meat", "savoury_snacks_pies" = "savoury snacks", "sodas_sweetened_bevs" = "sweetend drinks", "soups_stews"= "soups/stews", "sugar_sweet_spreads" = "sweetened spreads", "tea_coffee" = "tea/coffee", "trad_mixed_dishes" = "trad. dishes", "vegetables" = "veg.", "nonfried_roots_tubers_plntn_pots" = "root veg.", "fresh_juices" = "fresh juices"))
nairobi_lca2_noleg <- nairobi_lca2 + theme(legend.position = "none") # Plot without legend
# Plot but have names overlap
gt_2 <- ggplot_gtable(ggplot_build(nairobi_lca2)) # With legend
gt_2$layout$clip[gt_2$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_food_sold_nairobi.tiff", plot = gt_2, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_food_sold_nairobi.jpeg", plot = gt_2, dpi = 300, scale = 1)
plot(gt_2)


gt_2_nl <- ggplot_gtable(ggplot_build(nairobi_lca2_noleg)) # Without legend
gt_2_nl$layout$clip[gt_2_nl$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_food_sold_nairobi_noleg.tiff", plot = gt_2_nl, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_food_sold_nairobi_noleg.jpeg", plot = gt_2_nl, dpi = 300, scale = 1)
Food being advertised
# Reshape the results table into format for ggplot
hold <- results[42:65,] # Take only outlet variables
temp <- melt((hold), na.rm=TRUE) # Turn into long format
# Polar plot
nairobi_lca3 <- ggplot(temp, aes(x=Value, y=value, group = variable, colour=variable)) +
geom_line(size=1.2) + ylim(0,1) +
coord_polar() + labs(x = NULL, y = NULL, color = "Latent Class") + theme(axis.text.x = element_text(angle = 0, hjust = 1.5, size = 10)) +
theme(legend.position="bottom") + ggtitle("Food Advertised") + theme(plot.title = element_text(hjust = 0.5)) + scale_color_brewer(palette="Set3") + theme(axis.text.y=element_blank(), axis.ticks.y=element_blank()) + theme(plot.margin=unit(c(0.5,2,0.5,2),"cm")) + scale_x_discrete(labels = c("fats_oils" = "fats/oils", "fresh_fish_shellfish" = "fresh fish", "cakes_sweets" = "cakes/sweets", "fresh_meat_poultry" = "fresh meat", "fried_roots_tubers_plntn_pots" = "fried root veg.", "grain_cereal" = "grain/cereal", "legumes_pulses" = "legumes/pulses", "modern_mixed_dishes" = "m.dish", "nuts_seeds"= "nuts/seeds", "procssd_fried_fish" = "processed fish", "procssd_fried_meat_poultry" = "processed meat", "savoury_snacks_pies" = "savoury snacks", "sodas_sweetened_bevs" = "sweetend drinks", "soups_stews"= "soups/stews", "sugar_sweet_spreads" = "sweetened spreads", "tea_coffee" = "tea/coffee", "trad_mixed_dishes" = "trad. dishes", "vegetables" = "veg."))
nairobi_lca3_noleg <- nairobi_lca3 + theme(legend.position = "none") # Plot without legend
# Plot but have names overlap
gt_3 <- ggplot_gtable(ggplot_build(nairobi_lca3)) # With legend
gt_3$layout$clip[gt_3$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_food_adv_nairobi.tiff", plot = gt_3, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_food_adv_nairobi.jpeg", plot = gt_3, dpi = 300, scale = 1)
plot(gt_3)


gt_3_nl <- ggplot_gtable(ggplot_build(nairobi_lca3_noleg)) # Without legend
gt_3_nl$layout$clip[gt_3_nl$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_food_adv_nairobi_noleg.tiff", plot = gt_3_nl, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_food_adv_nairobi_noleg.jpeg", plot = gt_3_nl, dpi = 300, scale = 1)
Let’s join them together into a single plot.
library(gridExtra)
# Create blank plot to centre legend
blankPlot <- ggplot()+geom_blank(aes(1,1)) +
cowplot::theme_nothing()
# Join together plots into single plot
# Save as PDF
pdf("./Plots/nairobi_all_plots.pdf", width = 10, height = 10)
grid.arrange(gt_1_nl, gt_1_nla, gt_2_nl, gt_3_nl, legend, ncol = 2, nrow = 3,
widths = c(10, 10), heights = c(10, 10, 4))
dev.off()
null device
1
# Save as image/tiff file
tiff("./Plots/nairobi_all_plots.tiff", width = 10, height = 10, units = "in", res = 300)
grid.arrange(gt_1_nl, gt_1_nla, gt_2_nl, gt_3_nl, legend, ncol = 2, nrow = 3,
widths = c(10, 10), heights = c(10, 10, 4))
dev.off()
null device
1
Accra, Ghana
First, we assess how many latent classes.
# Subset Accra data only
accra <- ghana[ghana$location == "Accra"]
# Define variables to be used in LCA to estimate groups (too many variables?)
f <- with(accra,
cbind(# Type of outlet (restaurant, social marketing and billboards dropped as none)
outlet_w_advert, outlet_no_advert, advert_only, supermarket, shop, kiosk, stand_table_top, local_vendor, bar_pub, other_outlet, poster_adv, onsite_adv, painting_adv,
# Foods sold
grain_cereal, fresh_meat_poultry, fresh_fish_shellfish, procssd_fried_meat_poultry, procssd_fried_fish, trad_mixed_dishes, modern_mixed_dishes, soups_stews, fried_roots_tubers_plntn_pots, nonfried_roots_tubers_plntn_pots, fruits, vegetables, cakes_sweets, savoury_snacks_pies, sodas_sweetened_bevs, milk, fresh_juices, alcohol, sugar_sweet_spreads, tea_coffee, fats_oils, nuts_seeds, legumes_pulses, condiments, eggs, other,
# Advertisements (tea/coffee 0 so dropped, as was nuts/seeds and advert other)
adv_grain_cereal, adv_fresh_meat_poultry, adv_fresh_fish_shellfish, adv_procssd_fried_meat_poultry, adv_procssd_fried_fish, adv_trad_mixed_dishes, adv_modern_mixed_dishes, adv_soups_stews, adv_fried_roots_tubers_plntn_pots, adv_nonfried_roots_tubers_plntn_pots, adv_fruits, adv_vegetables, adv_cakes_sweets, adv_savoury_snacks_pies, adv_sodas_sweetened_bevs, adv_milk, adv_fresh_juices, adv_alcohol, adv_sugar_sweet_spreads, adv_fats_oils, adv_legumes_pulses, adv_condiments, adv_eggs)~1)
# Identify best number of groups
numbers <- c(1:10)
for (i in numbers) {
temp <- poLCA(f, accra, nclass=i, nrep=20, maxiter=100000, verbose=FALSE, na.rm=T)
assign(paste0("lca_all",i), temp)
rm(temp)
}
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
# Compare solutions
AIC <- c(rbind(lca_all1$aic, lca_all2$aic, lca_all3$aic, lca_all4$aic, lca_all5$aic,
lca_all6$aic, lca_all7$aic, lca_all8$aic, lca_all9$aic, lca_all10$aic))
BIC <- c(rbind(lca_all1$bic, lca_all2$bic, lca_all3$bic, lca_all4$bic, lca_all5$bic,
lca_all6$bic, lca_all7$bic, lca_all8$bic, lca_all9$bic, lca_all10$bic))
Gsq <- c(rbind(lca_all1$Gsq, lca_all2$Gsq, lca_all3$Gsq, lca_all4$Gsq, lca_all5$Gsq,
lca_all6$Gsq, lca_all7$Gsq, lca_all8$Gsq, lca_all9$Gsq, lca_all10$Gsq))
Chisq <- c(rbind(lca_all1$Chisq, lca_all2$Chisq, lca_all3$Chisq, lca_all4$Chisq, lca_all5$Chisq,
lca_all6$Chisq, lca_all7$Chisq, lca_all8$Chisq, lca_all9$Chisq, lca_all10$Chisq))
Groups <- c(1:10)
numb_grps_all <- cbind(Groups,AIC,BIC,Gsq,Chisq) # Put together in one table
write.table(numb_grps_all, "./number_of_groups_accra.txt", sep = "\t", row.names = FALSE) # Save
# Plot values
numb_grps_all <- as.data.frame(numb_grps_all)
plot1 <- ggplot(numb_grps_all, aes(x = Groups, y = AIC)) + geom_point() + xlab("Number of classes") + ylab("Akaike Information Criterion") + scale_x_continuous(limits=c(0, 10), breaks = seq(0,10,2))
ggsave("./Plots/accra_lca_aic.tiff", plot = plot1, dpi = 300, width = 7, height = 7)
ggsave("./Plots low res/accra_lca_aic.jpeg", plot = plot1, dpi = 300, width = 7, height = 7)
plot1
plot2 <- ggplot(numb_grps_all, aes(x = Groups, y = BIC)) + geom_point() + xlab("Number of classes") + ylab("Bayesian Information Criterion") + scale_x_continuous(limits=c(0, 10), breaks = seq(0,10,2))
ggsave("./Plots/accra_lca_bic.tiff", plot = plot2, dpi = 300, width = 7, height = 7)
ggsave("./Plots low res/accra_lca_bic.jpeg", plot = plot2, dpi = 300, width = 7, height = 7)

plot2
plot3 <- ggplot(numb_grps_all, aes(x = Groups, y = Gsq)) + geom_point() + xlab("Number of classes") + ylab("G-squared statistic") + scale_x_continuous(limits=c(0, 10), breaks = seq(0,10,2))
ggsave("./Plots/accra_lca_gsq.tiff", plot = plot3, dpi = 300, width = 7, height = 7)
ggsave("./Plots low res/accra_lca_gsq.jpeg", plot = plot3, dpi = 300, width = 7, height = 7)

plot3
plot4 <- ggplot(numb_grps_all, aes(x = Groups, y = Chisq)) + geom_point() + xlab("Number of classes") + ylab("Chi-squared statistic") + scale_x_continuous(limits=c(0, 10), breaks = seq(0,10,2))
ggsave("./Plots/accra_lca_chisq.tiff", plot = plot4, dpi = 300, width = 7, height = 7)
ggsave("./Plots low res/accra_lca_chisq.jpeg", plot = plot4, dpi = 300, width = 7, height = 7)

plot4

Hmmm, a 5 group solution seems best here - roughly where it levels off on three of the metrics. The final one doesn’t really help us at all. Let’s have a look at the cluster centres and start interpreting the clusters.
source("./tidy_poLCA_results_accra.R") # For 5 class solution, if change number of classes then need to manually edit
write.csv(results, "./cond_prob_accra.csv") # Save
results
I will incorporate their interpretation in the following sections below.
Outlet Type
library(ggplot2)
library(grid)
# Reshape the results table into format for ggplot
library(reshape2)
hold <- results[4:10,] # Take only outlet variables
temp <- melt((hold), na.rm=TRUE) # Turn into long format
# Polar plot
accra_lca1 <- ggplot(temp, aes(x=Value, y=value, group = variable, colour=variable)) +
geom_line(size=1.2) + ylim(0,1) +
coord_polar() + labs(x = NULL, y = NULL, color = "Latent Class") + theme(axis.text.x = element_text(angle = 0, hjust = 1.5, size = 10)) +
theme(legend.position="bottom") + ggtitle("Outlet Types") + theme(plot.title = element_text(hjust = 0.5)) + scale_color_brewer(palette="Set3") + theme(axis.text.y=element_blank(), axis.ticks.y=element_blank()) + theme(plot.margin=unit(c(0.5,2,0.5,2),"cm")) + scale_x_discrete(labels = c("bar_pub" = "bar/pub", "billboard_adv" = "billboard adv.", "local_vendor" = "local vendor", "onsite_adv" = "onsite adv.", "stand_table_top" = "tabletop", "other_outlet" = "other outlet"))
accra_lca1_noleg <- accra_lca1 + theme(legend.position = "none") # Plot without legend
# Plot but have names overlap
gt_1 <- ggplot_gtable(ggplot_build(accra_lca1)) # With legend
gt_1$layout$clip[gt_1$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_outlet_type_accra.tiff", plot = gt_1, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_outlet_type_accra.jpeg", plot = gt_1, dpi = 300, scale = 1)
plot(gt_1)


gt_1_nl <- ggplot_gtable(ggplot_build(accra_lca1_noleg)) # Without legend
gt_1_nl$layout$clip[gt_1_nl$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_outlet_type_accra_noleg.tiff", plot = gt_1_nl, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_outlet_type_accra_noleg.jpeg", plot = gt_1_nl, dpi = 300, scale = 1)
# Function to store legend
get_legend<-function(myggplot){
tmp <- ggplot_gtable(ggplot_build(myggplot))
leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
legend <- tmp$grobs[[leg]]
return(legend)
}
legend <- get_legend(accra_lca1) # Store legend
Advert Type
library(ggplot2)
library(grid)
# Reshape the results table into format for ggplot
library(reshape2)
hold <- results[c(1:3, 11:13),] # Take only outlet variables
temp <- melt((hold), na.rm=TRUE) # Turn into long format
# Polar plot
accra_lca1a <- ggplot(temp, aes(x=Value, y=value, group = variable, colour=variable)) +
geom_line(size=1.2) + ylim(0,1) +
coord_polar() + labs(x = NULL, y = NULL, color = "Latent Class") + theme(axis.text.x = element_text(angle = 0, hjust = 1.5, size = 10)) +
theme(legend.position="bottom") + ggtitle("Advert Types") + theme(plot.title = element_text(hjust = 0.5)) + scale_color_brewer(palette="Set3") + theme(axis.text.y=element_blank(), axis.ticks.y=element_blank()) + theme(plot.margin=unit(c(0.5,2,0.5,2),"cm")) + scale_x_discrete(labels = c("billboard_adv" = "billboard advert", "onsite_adv" = "onsite advert", "poster_adv" = "poster advert", "outlet_no_advert" = "outlet no advert", "outlet_w_advert"= "outlet with advert", "painting_adv" = "painting", "advert_only" = "advert"))
accra_lca1a_nolega <- accra_lca1a + theme(legend.position = "none") # Plot without legend
# Plot but have names overlap
gt_1a <- ggplot_gtable(ggplot_build(accra_lca1a)) # With legend
gt_1a$layout$clip[gt_1a$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_advert_type_accra.tiff", plot = gt_1a, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_advert_type_accra.jpeg", plot = gt_1a, dpi = 300, scale = 1)
plot(gt_1a)


gt_1_nla <- ggplot_gtable(ggplot_build(accra_lca1a_nolega)) # Without legend
gt_1_nla$layout$clip[gt_1_nla$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_advert_type_accra_noleg.tiff", plot = gt_1_nla, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_advert_type_accra_noleg.jpeg", plot = gt_1_nla, dpi = 300, scale = 1)
Food being sold
# Reshape the results table into format for ggplot
hold <- results[14:39,] # Take only outlet variables
temp <- melt((hold), na.rm=TRUE) # Turn into long format
# Polar plot
accra_lca2 <- ggplot(temp, aes(x=Value, y=value, group = variable, colour=variable)) +
geom_line(size=1.2) + ylim(0,1) +
coord_polar() + labs(x = NULL, y = NULL, color = "Latent Class") + theme(axis.text.x = element_text(angle = 0, hjust = 1.5, size = 10)) +
theme(legend.position="bottom") + ggtitle("Food Sold") + theme(plot.title = element_text(hjust = 0.5)) + scale_color_brewer(palette="Set3") + theme(axis.text.y=element_blank(), axis.ticks.y=element_blank()) + theme(plot.margin=unit(c(0.5,2,0.5,2),"cm")) + scale_x_discrete(labels = c("fats_oils" = "fats/oils", "fresh_fish_shellfish" = "fresh fish", "cakes_sweets" = "cakes/sweets", "fresh_meat_poultry" = "fresh meat", "fried_roots_tubers_plntn_pots" = "fried root veg.", "grain_cereal" = "grain/cereal", "legumes_pulses" = "legumes/pulses", "modern_mixed_dishes" = "m.dish", "nuts_seeds"= "nuts/seeds", "procssd_fried_fish" = "processed fish", "procssd_fried_meat_poultry" = "processed meat", "savoury_snacks_pies" = "savoury snacks", "sodas_sweetened_bevs" = "sweetened drinks", "soups_stews"= "soups/stews", "sugar_sweet_spreads" = "sweetened spreads", "tea_coffee" = "tea/coffee", "trad_mixed_dishes" = "trad. dishes", "vegetables" = "veg.", "nonfried_roots_tubers_plntn_pots" = "root veg.", "fresh_juices" = "fresh juices"))
accra_lca2_noleg <- accra_lca2 + theme(legend.position = "none") # Plot without legend
# Plot but have names overlap
gt_2 <- ggplot_gtable(ggplot_build(accra_lca2)) # With legend
gt_2$layout$clip[gt_2$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_food_sold_accra.tiff", plot = gt_2, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_food_sold_accra.jpeg", plot = gt_2, dpi = 300, scale = 1)
plot(gt_2)


gt_2_nl <- ggplot_gtable(ggplot_build(accra_lca2_noleg)) # Without legend
gt_2_nl$layout$clip[gt_2_nl$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_food_sold_accra_noleg.tiff", plot = gt_2_nl, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_food_sold_accra_noleg.jpeg", plot = gt_2_nl, dpi = 300, scale = 1)
Food being advertised
# Reshape the results table into format for ggplot
hold <- results[40:61,] # Take only outlet variables
temp <- melt((hold), na.rm=TRUE) # Turn into long format
# Polar plot
accra_lca3 <- ggplot(temp, aes(x=Value, y=value, group = variable, colour=variable)) +
geom_line(size=1.2) + ylim(0,1) +
coord_polar() + labs(x = NULL, y = NULL, color = "Latent Class") + theme(axis.text.x = element_text(angle = 0, hjust = 1.5, size = 10)) +
theme(legend.position="bottom") + ggtitle("Food Advertised") + theme(plot.title = element_text(hjust = 0.5)) + scale_color_brewer(palette="Set3") + theme(axis.text.y=element_blank(), axis.ticks.y=element_blank()) + theme(plot.margin=unit(c(0.5,2,0.5,2),"cm")) + scale_x_discrete(labels = c("fats_oils" = "fats/oils", "fresh_fish_shellfish" = "fresh fish", "cakes_sweets" = "cakes/sweets", "fresh_meat_poultry" = "fresh meat", "fried_roots_tubers_plntn_pots" = "fried root veg.", "grain_cereal" = "grain/cereal", "legumes_pulses" = "legumes", "modern_mixed_dishes" = "m.dish", "nuts_seeds"= "nuts/seeds", "procssd_fried_fish" = "processed fish", "procssd_fried_meat_poultry" = "processed meat", "savoury_snacks_pies" = "savoury snacks", "sodas_sweetened_bevs" = "sweetened drinks", "soups_stews"= "soups/stews", "sugar_sweet_spreads" = "sweetened spreads", "tea_coffee" = "tea/coffee", "trad_mixed_dishes" = "trad. dishes", "vegetables" = "veg."))
accra_lca3_noleg <- accra_lca3 + theme(legend.position = "none") # Plot without legend
# Plot but have names overlap
gt_3 <- ggplot_gtable(ggplot_build(accra_lca3)) # With legend
gt_3$layout$clip[gt_3$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_food_adv_accra.tiff", plot = gt_3, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_food_adv_accra.jpeg", plot = gt_3, dpi = 300, scale = 1)
plot(gt_3)


gt_3_nl <- ggplot_gtable(ggplot_build(accra_lca3_noleg)) # Without legend
gt_3_nl$layout$clip[gt_3_nl$layout$name == "panel"] <- "off"
ggsave("./Plots low res/lca_food_adv_accra_noleg.jpeg", plot = gt_3_nl, dpi = 300, scale = 1)
Let’s join them together into a single plot.
library(gridExtra)
# Create blank plot to centre legend
blankPlot <- ggplot()+geom_blank(aes(1,1)) +
cowplot::theme_nothing()
# Join together plots into single plot
# Save as PDF
pdf("./Plots/accra_all_plots.pdf", width = 10, height = 10)
grid.arrange(gt_1_nl, gt_1_nla, gt_2_nl, gt_3_nl, legend, ncol = 2, nrow = 3,
widths = c(10, 10), heights = c(10, 10, 4))
dev.off()
null device
1
# Save as image/tiff file
tiff("./Plots/accra_all_plots.tiff", width = 10, height = 10, units = "in", res = 300)
grid.arrange(gt_1_nl, gt_1_nla, gt_2_nl, gt_3_nl, legend, ncol = 2, nrow = 3,
widths = c(10, 10), heights = c(10, 10, 4))
dev.off()
null device
1
Ho
Last site is Ho. First, we assess how many latent classes.
# Subset Accra data only
ho <- ghana[ghana$location == "Ho"]
# Define variables to be used in LCA to estimate groups (too many variables?)
f <- with(ho,
cbind(# Type of outlet
outlet_w_advert, outlet_no_advert, advert_only, supermarket, shop, kiosk, stand_table_top, local_vendor, restaurant, bar_pub, other_outlet, billboard_adv, poster_adv, onsite_adv, painting_adv,
# Foods sold
grain_cereal, fresh_meat_poultry, fresh_fish_shellfish, procssd_fried_meat_poultry, procssd_fried_fish, trad_mixed_dishes, modern_mixed_dishes, soups_stews, fried_roots_tubers_plntn_pots, nonfried_roots_tubers_plntn_pots, fruits, vegetables, cakes_sweets, savoury_snacks_pies, sodas_sweetened_bevs, milk, fresh_juices, alcohol, sugar_sweet_spreads, tea_coffee, fats_oils, nuts_seeds, legumes_pulses, condiments, eggs, other,
# Advertisements
adv_grain_cereal, adv_fresh_meat_poultry, adv_fresh_fish_shellfish, adv_procssd_fried_meat_poultry, adv_procssd_fried_fish, adv_trad_mixed_dishes, adv_modern_mixed_dishes, adv_soups_stews, adv_fried_roots_tubers_plntn_pots, adv_nonfried_roots_tubers_plntn_pots, adv_fruits, adv_vegetables, adv_cakes_sweets, adv_savoury_snacks_pies, adv_sodas_sweetened_bevs, adv_milk, adv_fresh_juices, adv_alcohol, adv_sugar_sweet_spreads, adv_tea_coffee, adv_fats_oils, adv_nuts_seeds, adv_legumes_pulses, adv_condiments, adv_eggs, adv_other)~1)
# Identify best number of groups
numbers <- c(1:10)
for (i in numbers) {
temp <- poLCA(f, ho, nclass=i, nrep=20, maxiter=100000, verbose=FALSE, na.rm=T)
assign(paste0("lca_all",i), temp)
rm(temp)
}
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
ALERT: at least one manifest variable contained only one
outcome category, and has been removed from the analysis.
# Compare solutions
AIC <- c(rbind(lca_all1$aic, lca_all2$aic, lca_all3$aic, lca_all4$aic, lca_all5$aic,
lca_all6$aic, lca_all7$aic, lca_all8$aic, lca_all9$aic, lca_all10$aic))
BIC <- c(rbind(lca_all1$bic, lca_all2$bic, lca_all3$bic, lca_all4$bic, lca_all5$bic,
lca_all6$bic, lca_all7$bic, lca_all8$bic, lca_all9$bic, lca_all10$bic))
Gsq <- c(rbind(lca_all1$Gsq, lca_all2$Gsq, lca_all3$Gsq, lca_all4$Gsq, lca_all5$Gsq,
lca_all6$Gsq, lca_all7$Gsq, lca_all8$Gsq, lca_all9$Gsq, lca_all10$Gsq))
Chisq <- c(rbind(lca_all1$Chisq, lca_all2$Chisq, lca_all3$Chisq, lca_all4$Chisq, lca_all5$Chisq,
lca_all6$Chisq, lca_all7$Chisq, lca_all8$Chisq, lca_all9$Chisq, lca_all10$Chisq))
Groups <- c(1:10)
numb_grps_all <- cbind(Groups,AIC,BIC,Gsq,Chisq) # Put together in one table
write.table(numb_grps_all, "./number_of_groups_ho.txt", sep = "\t", row.names = FALSE) # Save
# Plot values
numb_grps_all <- as.data.frame(numb_grps_all)
plot1 <- ggplot(numb_grps_all, aes(x = Groups, y = AIC)) + geom_point() + xlab("Number of classes") + ylab("Akaike Information Criterion") + scale_x_continuous(limits=c(0, 10), breaks = seq(0,10,2))
ggsave("./Plots/ho_lca_aic.tiff", plot = plot1, dpi = 300, width = 7, height = 7)
ggsave("./Plots low res/ho_lca_aic.jpeg", plot = plot1, dpi = 300, width = 7, height = 7)
plot1
plot2 <- ggplot(numb_grps_all, aes(x = Groups, y = BIC)) + geom_point() + xlab("Number of classes") + ylab("Bayesian Information Criterion") + scale_x_continuous(limits=c(0, 10), breaks = seq(0,10,2))
ggsave("./Plots/ho_lca_bic.tiff", plot = plot2, dpi = 300, width = 7, height = 7)
ggsave("./Plots low res/ho_lca_bic.jpeg", plot = plot2, dpi = 300, width = 7, height = 7)

plot2
plot3 <- ggplot(numb_grps_all, aes(x = Groups, y = Gsq)) + geom_point() + xlab("Number of classes") + ylab("G-squared statistic") + scale_x_continuous(limits=c(0, 10), breaks = seq(0,10,2))
ggsave("./Plots/ho_lca_gsq.tiff", plot = plot3, dpi = 300, width = 7, height = 7)
ggsave("./Plots low res/ho_lca_gsq.jpeg", plot = plot3, dpi = 300, width = 7, height = 7)

plot3
plot4 <- ggplot(numb_grps_all, aes(x = Groups, y = Chisq)) + geom_point() + xlab("Number of classes") + ylab("Chi-squared statistic") + scale_x_continuous(limits=c(0, 10), breaks = seq(0,10,2))
ggsave("./Plots/ho_lca_chisq.tiff", plot = plot4, dpi = 300, width = 7, height = 7)
ggsave("./Plots low res/ho_lca_chisq.jpeg", plot = plot4, dpi = 300, width = 7, height = 7)

plot4

Hmmm, a 6 group solution seems best here - roughly where it levels off on three of the metrics. The final one doesn’t really help us at all. Let’s have a look at the cluster centres and start interpreting the clusters.
source("./tidy_poLCA_results_ho.R") # For 6 class solution, if change number of classes then need to manually edit
write.csv(results, "./cond_prob_ho.csv") # Save
results
We will interpret each latent class like before - by variable type.
Outlet Type
library(ggplot2)
library(grid)
# Reshape the results table into format for ggplot
library(reshape2)
hold <- results[4:11,] # Take only outlet variables
temp <- melt((hold), na.rm=TRUE) # Turn into long format
# Polar plot
ho_lca1 <- ggplot(temp, aes(x=Value, y=value, group = variable, colour=variable)) +
geom_line(size=1.2) + ylim(0,1) +
coord_polar() + labs(x = NULL, y = NULL, color = "Latent Class") + theme(axis.text.x = element_text(angle = 0, hjust = 1.5, size = 10)) +
theme(legend.position="bottom") + ggtitle("Outlet Types") + theme(plot.title = element_text(hjust = 0.5)) + scale_color_brewer(palette="Set3") + theme(axis.text.y=element_blank(), axis.ticks.y=element_blank()) + theme(plot.margin=unit(c(0.5,2,0.5,2),"cm")) + scale_x_discrete(labels = c("bar_pub" = "bar/pub", "billboard_adv" = "billboard adv.", "local_vendor" = "local vendor", "onsite_adv" = "onsite adv.", "stand_table_top" = "tabletop", "poster_adv" = "poster adv.", "other_adv" = "other adv.", "outlet_no_advert" = "outlet no adv.", "outlet_w_advert"= "outlet with adv.", "painting_adv" = "painting adv.", "poster_adv" = "poster adv.", "advert_only" = "advert", "other_outlet" = "other outlet", "soc_markt_adv" = "social media adv."))
ho_lca1_noleg <- ho_lca1 + theme(legend.position = "none") # Plot without legend
# Plot but have names overlap
gt_1 <- ggplot_gtable(ggplot_build(ho_lca1)) # With legend
gt_1$layout$clip[gt_1$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_outlet_type_ho.tiff", plot = gt_1, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_outlet_type_ho.jpeg", plot = gt_1, dpi = 300, scale = 1)
plot(gt_1)


gt_1_nl <- ggplot_gtable(ggplot_build(ho_lca1_noleg)) # Without legend
gt_1_nl$layout$clip[gt_1_nl$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_outlet_type_ho_noleg.tiff", plot = gt_1_nl, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_outlet_type_ho_noleg.jpeg", plot = gt_1_nl, dpi = 300, scale = 1)
# Function to store legend
get_legend<-function(myggplot){
tmp <- ggplot_gtable(ggplot_build(myggplot))
leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
legend <- tmp$grobs[[leg]]
return(legend)
}
legend <- get_legend(ho_lca1) # Store legend
Advert Type
library(ggplot2)
library(grid)
# Reshape the results table into format for ggplot
library(reshape2)
hold <- results[c(1:3, 12:15),] # Take only outlet variables
temp <- melt((hold), na.rm=TRUE) # Turn into long format
# Polar plot
ho_lca2a <- ggplot(temp, aes(x=Value, y=value, group = variable, colour=variable)) +
geom_line(size=1.2) + ylim(0,1) +
coord_polar() + labs(x = NULL, y = NULL, color = "Latent Class") + theme(axis.text.x = element_text(angle = 0, hjust = 1.5, size = 10)) +
theme(legend.position="bottom") + ggtitle("Advert Types") + theme(plot.title = element_text(hjust = 0.5)) + scale_color_brewer(palette="Set3") + theme(axis.text.y=element_blank(), axis.ticks.y=element_blank()) + theme(plot.margin=unit(c(0.5,2,0.5,2),"cm")) + scale_x_discrete(labels = c("billboard_adv" = "billboard advert", "onsite_adv" = "onsite advert", "poster_adv" = "poster advert", "outlet_no_advert" = "outlet no advert", "outlet_w_advert"= "outlet with advert", "painting_adv" = "painting", "advert_only" = "advert"))
ho_lca2a_nolega <- ho_lca2a + theme(legend.position = "none") # Plot without legend
# Plot but have names overlap
gt_1a <- ggplot_gtable(ggplot_build(ho_lca2a)) # With legend
gt_1a$layout$clip[gt_1a$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_advert_type_ho.tiff", plot = gt_1a, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_advert_type_ho.jpeg", plot = gt_1a, dpi = 300, scale = 1)
plot(gt_1a)


gt_1_nla <- ggplot_gtable(ggplot_build(ho_lca2a_nolega)) # Without legend
gt_1_nla$layout$clip[gt_1_nla$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_advert_type_ho_noleg.tiff", plot = gt_1_nla, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_advert_type_ho_noleg.jpeg", plot = gt_1_nla, dpi = 300, scale = 1)
Food being sold
# Reshape the results table into format for ggplot
hold <- results[16:41,] # Take only outlet variables
temp <- melt((hold), na.rm=TRUE) # Turn into long format
# Polar plot
ho_lca2 <- ggplot(temp, aes(x=Value, y=value, group = variable, colour=variable)) +
geom_line(size=1.2) + ylim(0,1) +
coord_polar() + labs(x = NULL, y = NULL, color = "Latent Class") + theme(axis.text.x = element_text(angle = 0, hjust = 1.5, size = 10)) +
theme(legend.position="bottom") + ggtitle("Food Sold") + theme(plot.title = element_text(hjust = 0.5)) + scale_color_brewer(palette="Set3") + theme(axis.text.y=element_blank(), axis.ticks.y=element_blank()) + theme(plot.margin=unit(c(0.5,2,0.5,2),"cm")) + scale_x_discrete(labels = c("fats_oils" = "fats/oils", "fresh_fish_shellfish" = "fresh fish", "cakes_sweets" = "cakes/sweets", "fresh_meat_poultry" = "fresh meat", "fried_roots_tubers_plntn_pots" = "fried root veg.", "grain_cereal" = "grain/cereal", "legumes_pulses" = "legumes/pulses", "modern_mixed_dishes" = "m.dish", "nuts_seeds"= "nuts/seeds", "procssd_fried_fish" = "processed fish", "procssd_fried_meat_poultry" = "processed meat", "savoury_snacks_pies" = "savoury snacks", "sodas_sweetened_bevs" = "sweetened drinks", "soups_stews"= "soups/stews", "sugar_sweet_spreads" = "sweetened spreads", "tea_coffee" = "tea/coffee", "trad_mixed_dishes" = "trad. dishes", "vegetables" = "veg.", "nonfried_roots_tubers_plntn_pots" = "root veg.", "fresh_juices" = "fresh juices"))
ho_lca2_noleg <- ho_lca2 + theme(legend.position = "none") # Plot without legend
# Plot but have names overlap
gt_2 <- ggplot_gtable(ggplot_build(ho_lca2)) # With legend
gt_2$layout$clip[gt_2$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_food_sold_ho.tiff", plot = gt_2, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_food_sold_ho.jpeg", plot = gt_2, dpi = 300, scale = 1)
plot(gt_2)


gt_2_nl <- ggplot_gtable(ggplot_build(ho_lca2_noleg)) # Without legend
gt_2_nl$layout$clip[gt_2_nl$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_food_sold_ho_noleg.tiff", plot = gt_2_nl, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_food_sold_ho_noleg.jpeg", plot = gt_2_nl, dpi = 300, scale = 1)
Food being advertised
# Reshape the results table into format for ggplot
hold <- results[42:66,] # Take only outlet variables
temp <- melt((hold), na.rm=TRUE) # Turn into long format
# Polar plot
ho_lca3 <- ggplot(temp, aes(x=Value, y=value, group = variable, colour=variable)) +
geom_line(size=1.2) + ylim(0,1) +
coord_polar() + labs(x = NULL, y = NULL, color = "Latent Class") + theme(axis.text.x = element_text(angle = 0, hjust = 1.5, size = 10)) +
theme(legend.position="bottom") + ggtitle("Food Advertised") + theme(plot.title = element_text(hjust = 0.5)) + scale_color_brewer(palette="Set3") + theme(axis.text.y=element_blank(), axis.ticks.y=element_blank()) + theme(plot.margin=unit(c(0.5,2,0.5,2),"cm")) + scale_x_discrete(labels = c("fats_oils" = "fats/oils", "fresh_fish_shellfish" = "fresh fish", "cakes_sweets" = "cakes/sweets", "fresh_meat_poultry" = "fresh meat", "nonfried_roots_tubers_plntn_pots" = "non fried root veg.", "fried_roots_tubers_plntn_pots" = "fried root veg.", "grain_cereal" = "grain/cereal", "legumes_pulses" = "legumes", "modern_mixed_dishes" = "m.dish", "nuts_seeds"= "nuts/seeds", "procssd_fried_fish" = "processed fish", "procssd_fried_meat_poultry" = "processed meat", "savoury_snacks_pies" = "savoury snacks", "sodas_sweetened_bevs" = "sweetened drinks", "soups_stews"= "soups/stews", "sugar_sweet_spreads" = "sweetened spreads", "tea_coffee" = "tea/coffee", "trad_mixed_dishes" = "trad. dishes", "vegetables" = "veg.", "fesh_juices" = "fresh juice"))
ho_lca3_noleg <- ho_lca3 + theme(legend.position = "none") # Plot without legend
# Plot but have names overlap
gt_3 <- ggplot_gtable(ggplot_build(ho_lca3)) # With legend
gt_3$layout$clip[gt_3$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_food_adv_ho.tiff", plot = gt_3, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_food_adv_ho.jpeg", plot = gt_3, dpi = 300, scale = 1)
plot(gt_3)


gt_3_nl <- ggplot_gtable(ggplot_build(ho_lca3_noleg)) # Without legend
gt_3_nl$layout$clip[gt_3_nl$layout$name == "panel"] <- "off"
ggsave("./Plots/lca_food_adv_ho_noleg.tiff", plot = gt_3_nl, scale = 1, dpi = 300)
ggsave("./Plots low res/lca_food_adv_ho_noleg.jpeg", plot = gt_3_nl, dpi = 300, scale = 1)
Join all plots together into a single one.
library(gridExtra)
# Create blank plot to centre legend
blankPlot <- ggplot()+geom_blank(aes(1,1)) +
cowplot::theme_nothing()
# Join together plots into single plot
# Save as PDF
pdf("./Plots/ho_all_plots.pdf", width = 10, height = 10)
grid.arrange(gt_1_nl, gt_1_nla, gt_2_nl, gt_3_nl, legend, ncol = 2, nrow = 3,
widths = c(10, 10), heights = c(10, 10, 4))
dev.off()
null device
1
# Save as image/tiff file
tiff("./Plots/ho_all_plots.tiff", width = 10, height = 10, units = "in", res = 300)
grid.arrange(gt_1_nl, gt_1_nla, gt_2_nl, gt_3_nl, legend, ncol = 2, nrow = 3,
widths = c(10, 10), heights = c(10, 10, 4))
dev.off()
null device
1
LS0tCnRpdGxlOiAiQ2xhc3NpZnlpbmcgdGhlIGZvb2QgZW52aXJvbm1lbnQiCmF1dGhvcjogTWFyayBBIEdyZWVuCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCldlIGhhdmUgY29sbGVjdGVkIGEgY29tcGxleCBhbW91bnQgb2YgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGZvb2QgZW52aXJvbm1lbnRzIHdpdGhpbiB0aGUgdGhyZWUgbG9jYXRpb25zOiBBY2NyYSBhbmQgSG8gaW4gR2hhbmEsIGFuZCBOYWlyb2JpIGluIEtlbnlhLiBUaGUgZm9sbG93aW5nIGRvY3VtZW50IHdpbGwgdXNlIExhdGVudCBDbGFzcyBBbmFseXNpcyB0byBjaGFyYWN0ZXJpc2UgZWFjaCBmb29kIGVudmlyb25tZW50LiBGaXJzdCwgbGV0J3MgbG9hZCB0aGUgZGF0YSBhbmQgdGhlbiB3ZSB3aWxsIGFuYWx5c2UgZWFjaCBjb250ZXh0IHNlcGFyYXRlbHkuCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIFNldCB1cApzZXQuc2VlZCgyODExOTApCmxpYnJhcnkocG9MQ0EpCmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeShnZ3Bsb3QyKQoKIyBMb2FkIGFuZCB0aWR5IGRhdGEKIyBHaGFuYQpzb3VyY2UoIi4vdGlkeV9naXNfZGF0YV9naGFuYS5SIikKZ2hhbmEgPC0gYXMuZGF0YS50YWJsZShvdXRsZXRzKQoKIyBwb0xDQSByZXF1aXJlcyBvbmx5IHBvc2l0aXZlIHZhbHVlcyBpLmUuIDEvMiBub3QgMC8xIC0gc28gYWRkIDEgb250byBldmVyeXRoaW5nIQpnaGFuYVssYygxNTo0MCw1MTo3Niw5NjoxMTEpXTwtIGdoYW5hWyxjKDE1OjQwLDUxOjc2LDk2OjExMSldICsgMQoKI0tlbnlhCnNvdXJjZSgiLi90aWR5X2dpc19kYXRhX2tlbnlhLlIiKQpuYWlyb2JpIDwtIGFzLmRhdGEudGFibGUob3V0bGV0cykKcm0ob3V0bGV0cykKCm5haXJvYmlbLGMoMjM6NDgsNTE6NTYsNTg6ODIsOTM6MTAzKV0gPC0gbmFpcm9iaVssYygyMzo0OCw1MTo1Niw1ODo4Miw5MzoxMDMpXSArIDEKbmFpcm9iaSRvdXRsZXRfdHlwZVtuYWlyb2JpJG91dGxldF90eXBlID09IDldIDwtIDcgIyBSZWNvZGUgdG8gaGVscCBMQ0EgcHJvY2VzcyAoZWxzZSB3aWxsIGVzdGltYXRlIGFsbCBwYXJhbWV0ZXIgdmFsdWVzIGluIGJldHdlZW4pCm5haXJvYmkkb3V0bGV0X3R5cGVbbmFpcm9iaSRvdXRsZXRfdHlwZSA9PSA5Nl0gPC0gOCAKCmBgYAoKI05haXJibywgS2VueWEKCldlIHdpbGwgc3RhcnQgd2l0aCB0aGUgZGF0YSBmb3IgTmFpcm9iaS4gSSBoYXZlIHJ1biB0aGUgYW5hbHlzaXMgZm9yIGFzIG11Y2ggZGF0YSBhcyB3ZSBoYXZlIHRoYXQgaXMgZGlyZWN0bHkgY29tcGFyYWJsZSB0byB0aGUgR2hhbmEgZGF0YSB0byBhaWQgaW50ZXJwcmV0YXRpb24uIFRoaXMgaW5jbHVkZXM6CgoqIE91dGxldCB0eXBlIC0gd2hhdCB0aGUgb3V0bGV0IHdhcywgaGV0aGVyIGl0IGNvbnRhaW5zIGFuIGFkdmVydGlzZW1lbnQgYW5kIHdoYXQgdHlwZSBvZiBhZHZlcnQgaXQgd2FzCiogRm9vZHMgc29sZCAtIHNwbGl0IGJ5IHR5cGUgb2YgZm9vZCBlLmcuIGdyYWlucy9jZXJlYWxzLCBmcmVzc2ggbWVhdCAmIHBvdWx0cnksIGZydWl0IGV0YwoqIEZvb2RzIGJlaW5nIGFkdmVydGlzZWQgLSBieSBzYW1lIGZvb2QgY2F0ZWdvcmllcyBhcyBhYm92ZQoKT25lIGlzc3VlIGlzIHRoYXQgd2UgYXJlIGVzdGltYXRpbmcgYSBsb3Qgb2YgcGFyYW1ldGVycyBoZXJlIChkdWUgdG8gbGFyZ2UgYW1vdW50IG9mIHZhcmlhYmxlcykuIFNob3VsZCB3ZSBsb29rIHRvIHJlZHVjZSB0aGUgbnVtYmVyIG9mIHZhcmlhYmxlcyAoaS5lLiB1c2luZyBQQ0EpIHRoZW4gY2x1c3RlciB0aGVtIGZpcnN0PyBGb3Igbm93IEkgaGF2ZSBub3QgZG9uZSB0aGlzIGJ1dCBzaW1wbHkgcnVuIHRoZSBMQ0EgYnkgaXRzZWxmLiAKCldlIHdhbnQgdG8gZmluZCB0aGUgJ2Jlc3QnIG51bWJlciBvZiBsYXRlbnQgY2xhc3NlcyB0aGF0IGRlc2NyaWJlcyB0aGUgZGF0YSB3ZWxsLiBBbiBpbmNyZWFzaW5nIG51bWJlciBvZiBjbHVzdGVycyB3aWxsIGxpa2VseSBhbHdheXMgcHJvZHVjZSBhIGJldHRlciBmaXR0aW5nIG1vZGVsIChvbiBzb21lIG1ldHJpY3MpLCBob3dldmVyIGFsc28gYnJpbmdzIGFkZGVkIGNvbXBsZXhpdHkgdGhyb3VnaCBhIGxhcmdlciBudW1iZXIgb2YgZ3JvdXBzLiBXaGF0IHdlIHdhbnQgdG8gYWNoaWV2ZSBpcyBhIHBhcnNpbW9uaW91cyBzb2x1dGlvbiB0aGF0IG1heGltaXNlcyB0aGUgbW9kZWwgZml0LCBidXQgbWluaW1pc2VzIHRoZSBudW1iZXIgb2YgZ3JvdXBzLiBUbyBkbyB0aGlzLCB3ZSB3aWxsIHJ1biB0aGUgTENBIGZvciBhIHJhbmdlIG9mIHNvbHV0aW9ucyBiZXR3ZWVuIDEgYW5kIDEwIChJIGFtIGh5cG90aGVzaXNpbmcgdGhhdCBtb3JlIHRoYW4gMTAgY2xhc3NlcyBpcyBub3QgdXNlZnVsKS4gV2Ugd2lsbCB0aGVuIGNvbXBhcmUgbW9kZWwgZml0IGJldHdlZW4gdGhlc2Ugc29sdXRpb25zLiBXaGF0IHdlIGFyZSBsb29raW5nIGZvciBpcyB0aGUgcG9pbnQgd2hlcmUgYWRkaXRpb25hbCBncm91cHMgaW4gdGhlIG1vZGVsIHByb2R1Y2VzIGxpdHRsZSBhZGRpdGlvbmFsIG1vZGVsIGJlbmVmaXQgLSB0aGlzIGlzIHJlZmVyZWQgdG8gYXMgdGhlICdrbmVlIHBvaW50Jy4gSSBoYXZlIGRvbmUgdGhpcyBmb3IgNCBjb21tb24gbWV0cmljcyBpbiBMQ0EgcmVzZWFyY2g6CgoxLiBBa2Fpa2UgSW5mb3JtYXRpb24gQ3JpdGVyaW9uIChBSUMpCjIuIEJheWVzaWFuIEluZm9ybWF0aW9uIENyaXRlcmlvbiAoQklDKQozLiBHLXNxdWFyZWQgc3RhdGlzdGljCjQuIENoaS1zcXVhcmVkIHRlc3Qgc3RhdGlzdGljCgpTbWFsbGVyIHZhbHVlcyBmb3IgZWFjaCBtZXRyaWMgcmVwcmVzZW50IGEgYmV0dGVyIGZpdHRpbmcgbW9kZWwuCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIERlZmluZSB2YXJpYWJsZXMgdG8gYmUgdXNlZCBpbiBMQ0EgdG8gZXN0aW1hdGUgZ3JvdXBzICh0b28gbWFueSB2YXJpYWJsZXM/KQpmIDwtIHdpdGgobmFpcm9iaSwgCiAgICAgICAgICBjYmluZCgjIFR5cGUgb2Ygb3V0bGV0CiAgICAgICAgICAgb3V0bGV0X3dfYWR2ZXJ0LCBvdXRsZXRfbm9fYWR2ZXJ0LCBhZHZlcnRfb25seSwgc3VwZXJtYXJrZXQsIHNob3AsIGtpb3NrLCBzdGFuZF90YWJsZV90b3AsIGxvY2FsX3ZlbmRvciwgcmVzdGF1cmFudCwgYmFyX3B1Yiwgb3RoZXJfb3V0bGV0LCBiaWxsYm9hcmRfYWR2LCBwb3N0ZXJfYWR2LCBvbnNpdGVfYWR2LCBwYWludGluZ19hZHYsCiAgICAgICAgICAgIyBGb29kcyBzb2xkCiAgICAgICAgICAgZ3JhaW5fY2VyZWFsLCBmcmVzaF9tZWF0X3BvdWx0cnksIGZyZXNoX2Zpc2hfc2hlbGxmaXNoLCBwcm9jc3NkX2ZyaWVkX21lYXRfcG91bHRyeSwgcHJvY3NzZF9mcmllZF9maXNoLCB0cmFkX21peGVkX2Rpc2hlcywgbW9kZXJuX21peGVkX2Rpc2hlcywgc291cHNfc3Rld3MsIGZyaWVkX3Jvb3RzX3R1YmVyc19wbG50bl9wb3RzLCBub25mcmllZF9yb290c190dWJlcnNfcGxudG5fcG90cywgZnJ1aXRzLCB2ZWdldGFibGVzLCBjYWtlc19zd2VldHMsIHNhdm91cnlfc25hY2tzX3BpZXMsIHNvZGFzX3N3ZWV0ZW5lZF9iZXZzLCBtaWxrLCBmcmVzaF9qdWljZXMsIGFsY29ob2wsIHN1Z2FyX3N3ZWV0X3NwcmVhZHMsIHRlYV9jb2ZmZWUsIGZhdHNfb2lscywgbnV0c19zZWVkcywgbGVndW1lc19wdWxzZXMsIGNvbmRpbWVudHMsIGVnZ3MsIG90aGVyLAogICAgICAgICAgICMgQWR2ZXJ0aXNlbWVudHMgKGZyZXNoIGp1aWNlcyBtaXNzaW5nKQogICAgICAgICAgIGFkdl9ncmFpbl9jZXJlYWwsIGFkdl9mcmVzaF9tZWF0X3BvdWx0cnksIGFkdl9mcmVzaF9maXNoX3NoZWxsZmlzaCwgYWR2X3Byb2Nzc2RfZnJpZWRfbWVhdF9wb3VsdHJ5LCBhZHZfcHJvY3NzZF9mcmllZF9maXNoLCBhZHZfdHJhZF9taXhlZF9kaXNoZXMsIGFkdl9tb2Rlcm5fbWl4ZWRfZGlzaGVzLCBhZHZfc291cHNfc3Rld3MsIGFkdl9mcmllZF9yb290c190dWJlcnNfcGxudG5fcG90cywgYWR2X25vbmZyaWVkX3Jvb3RzX3R1YmVyc19wbG50bl9wb3RzLCBhZHZfZnJ1aXRzLCBhZHZfdmVnZXRhYmxlcywgYWR2X2Nha2VzX3N3ZWV0cywgYWR2X3Nhdm91cnlfc25hY2tzX3BpZXMsIGFkdl9zb2Rhc19zd2VldGVuZWRfYmV2cywgYWR2X21pbGssIGFkdl9hbGNvaG9sLCBhZHZfc3VnYXJfc3dlZXRfc3ByZWFkcywgYWR2X3RlYV9jb2ZmZWUsIGFkdl9mYXRzX29pbHMsIGFkdl9udXRzX3NlZWRzLCBhZHZfbGVndW1lc19wdWxzZXMsIGFkdl9jb25kaW1lbnRzLCBhZHZfZWdncywgYWR2X290aGVyKX4xKQoKIyBJZGVudGlmeSBiZXN0IG51bWJlciBvZiBncm91cHMKCm51bWJlcnMgPC0gYygxOjEwKQoKZm9yIChpIGluIG51bWJlcnMpIHsKICB0ZW1wIDwtIHBvTENBKGYsIG5haXJvYmksIG5jbGFzcz1pLCBucmVwPTIwLCBtYXhpdGVyPTEwMDAwMCwgdmVyYm9zZT1GQUxTRSwgbmEucm09VCkKICBhc3NpZ24ocGFzdGUwKCJsY2FfYWxsIixpKSwgdGVtcCkKICBybSh0ZW1wKQp9CgojIENvbXBhcmUgc29sdXRpb25zCkFJQyA8LSBjKHJiaW5kKGxjYV9hbGwxJGFpYywgbGNhX2FsbDIkYWljLCBsY2FfYWxsMyRhaWMsIGxjYV9hbGw0JGFpYywgbGNhX2FsbDUkYWljLAogICAgICAgICAgICAgICBsY2FfYWxsNiRhaWMsIGxjYV9hbGw3JGFpYywgbGNhX2FsbDgkYWljLCBsY2FfYWxsOSRhaWMsIGxjYV9hbGwxMCRhaWMpKQpCSUMgPC0gYyhyYmluZChsY2FfYWxsMSRiaWMsIGxjYV9hbGwyJGJpYywgbGNhX2FsbDMkYmljLCBsY2FfYWxsNCRiaWMsIGxjYV9hbGw1JGJpYywKICAgICAgICAgICAgICAgbGNhX2FsbDYkYmljLCBsY2FfYWxsNyRiaWMsIGxjYV9hbGw4JGJpYywgbGNhX2FsbDkkYmljLCBsY2FfYWxsMTAkYmljKSkKR3NxIDwtIGMocmJpbmQobGNhX2FsbDEkR3NxLCBsY2FfYWxsMiRHc3EsIGxjYV9hbGwzJEdzcSwgbGNhX2FsbDQkR3NxLCBsY2FfYWxsNSRHc3EsCiAgICAgICAgICAgICAgIGxjYV9hbGw2JEdzcSwgbGNhX2FsbDckR3NxLCBsY2FfYWxsOCRHc3EsIGxjYV9hbGw5JEdzcSwgbGNhX2FsbDEwJEdzcSkpCkNoaXNxIDwtIGMocmJpbmQobGNhX2FsbDEkQ2hpc3EsIGxjYV9hbGwyJENoaXNxLCBsY2FfYWxsMyRDaGlzcSwgbGNhX2FsbDQkQ2hpc3EsIGxjYV9hbGw1JENoaXNxLAogICAgICAgICAgICAgICAgIGxjYV9hbGw2JENoaXNxLCBsY2FfYWxsNyRDaGlzcSwgbGNhX2FsbDgkQ2hpc3EsIGxjYV9hbGw5JENoaXNxLCBsY2FfYWxsMTAkQ2hpc3EpKQpHcm91cHMgPC0gYygxOjEwKQpudW1iX2dycHNfYWxsIDwtIGNiaW5kKEdyb3VwcyxBSUMsQklDLEdzcSxDaGlzcSkgIyBQdXQgdG9nZXRoZXIgaW4gb25lIHRhYmxlCndyaXRlLnRhYmxlKG51bWJfZ3Jwc19hbGwsICJudW1iZXJfb2ZfZ3JvdXBzX25haXJvYmkudHh0Iiwgc2VwID0gIlx0Iiwgcm93Lm5hbWVzID0gRkFMU0UpICMgU2F2ZQoKIyBQbG90IHZhbHVlcwpudW1iX2dycHNfYWxsIDwtIGFzLmRhdGEuZnJhbWUobnVtYl9ncnBzX2FsbCkKcGxvdDEgPC0gZ2dwbG90KG51bWJfZ3Jwc19hbGwsIGFlcyh4ID0gR3JvdXBzLCB5ID0gQUlDKSkgKyBnZW9tX3BvaW50KCkgKyB4bGFiKCJOdW1iZXIgb2YgY2xhc3NlcyIpICsgeWxhYigiQWthaWtlIEluZm9ybWF0aW9uIENyaXRlcmlvbiIpICsgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKDAsIDEwKSwgYnJlYWtzID0gc2VxKDAsMTAsMikpCmdnc2F2ZSgiLi9QbG90cy9uYWlyb2JpX2xjYV9haWMudGlmZiIsIHBsb3QgPSBwbG90MSwgZHBpID0gMzAwLCB3aWR0aCA9IDcsIGhlaWdodCA9IDcpCmdnc2F2ZSgiLi9QbG90cyBsb3cgcmVzL25haXJvYmlfbGNhX2FpYy5qcGVnIiwgcGxvdCA9IHBsb3QxLCBkcGkgPSAzMDAsIHdpZHRoID0gNywgaGVpZ2h0ID0gNykKcGxvdDEKCnBsb3QyIDwtIGdncGxvdChudW1iX2dycHNfYWxsLCBhZXMoeCA9IEdyb3VwcywgeSA9IEJJQykpICsgZ2VvbV9wb2ludCgpICsgeGxhYigiTnVtYmVyIG9mIGNsYXNzZXMiKSArIHlsYWIoIkJheWVzaWFuIEluZm9ybWF0aW9uIENyaXRlcmlvbiIpICsgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKDAsIDEwKSwgYnJlYWtzID0gc2VxKDAsMTAsMikpCmdnc2F2ZSgiLi9QbG90cy9uYWlyb2JpX2xjYV9iaWMudGlmZiIsIHBsb3QgPSBwbG90MiwgZHBpID0gMzAwLCB3aWR0aCA9IDcsIGhlaWdodCA9IDcpCmdnc2F2ZSgiLi9QbG90cyBsb3cgcmVzL25haXJvYmlfbGNhX2JpYy5qcGVnIiwgcGxvdCA9IHBsb3QyLCBkcGkgPSAzMDAsIHdpZHRoID0gNywgaGVpZ2h0ID0gNykKcGxvdDIKCnBsb3QzIDwtIGdncGxvdChudW1iX2dycHNfYWxsLCBhZXMoeCA9IEdyb3VwcywgeSA9IEdzcSkpICsgZ2VvbV9wb2ludCgpICsgeGxhYigiTnVtYmVyIG9mIGNsYXNzZXMiKSArIHlsYWIoIkctc3F1YXJlZCBzdGF0aXN0aWMiKSArIHNjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygwLCAxMCksIGJyZWFrcyA9IHNlcSgwLDEwLDIpKQpnZ3NhdmUoIi4vUGxvdHMvbmFpcm9iaV9sY2FfZ3NxLnRpZmYiLCBwbG90ID0gcGxvdDMsIGRwaSA9IDMwMCwgd2lkdGggPSA3LCBoZWlnaHQgPSA3KQpnZ3NhdmUoIi4vUGxvdHMgbG93IHJlcy9uYWlyb2JpX2xjYV9iaWMuanBlZyIsIHBsb3QgPSBwbG90MywgZHBpID0gMzAwLCB3aWR0aCA9IDcsIGhlaWdodCA9IDcpCnBsb3QzCgpwbG90NCA8LSBnZ3Bsb3QobnVtYl9ncnBzX2FsbCwgYWVzKHggPSBHcm91cHMsIHkgPSBDaGlzcSkpICsgZ2VvbV9wb2ludCgpICsgeGxhYigiTnVtYmVyIG9mIGNsYXNzZXMiKSArIHlsYWIoIkNoaS1zcXVhcmVkIHN0YXRpc3RpYyIpICsgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKDAsIDEwKSwgYnJlYWtzID0gc2VxKDAsMTAsMikpCmdnc2F2ZSgiLi9QbG90cy9uYWlyb2JpX2xjYV9jaGlzcS50aWZmIiwgcGxvdCA9IHBsb3Q0LCBkcGkgPSAzMDAsIHdpZHRoID0gNywgaGVpZ2h0ID0gNykKZ2dzYXZlKCIuL1Bsb3RzIGxvdyByZXMvbmFpcm9iaV9sY2FfY2hpc3EuanBlZyIsIHBsb3QgPSBwbG90NCwgZHBpID0gMzAwLCB3aWR0aCA9IDcsIGhlaWdodCA9IDcpCnBsb3Q0CgpgYGAKClRoZSBtb2RlbHMgc3VnZ2VzdCB0aGUgZm9sbG93aW5nOgoKMS4gQUlDIC0gQW4gaW5jcmVhc2luZyBudW1iZXIgb2YgZ3JvdXBzIHByb2R1Y2VzIGJldHRlciBmaXR0aW5nIG1vZGVscywgYnV0IHdpdGggZGltaW5pc2hpbmcgcmV0dXJucy4gQXQgNSBncm91cHMsIHRoZSBpbXByb3ZlbWVudHMgc3RheSByZWxhdGl2ZWx5IGZsYXQgc3VnZ2VzdGluZyB0aGF0IHRoZXkgYXJlIG5vdCBhZGRpbmcgbXVjaCB0byB0aGUgc29sdXRpb24uCjIuIEJJQyAtIFdlIGJyb2FkbHkgc2VlIGFuIGltcHJvdmluZyBzb2x1dGlvbiB1cHRvIDUgY2xhc3Nlcywgd2hlcmVieSBtb2RlbCBwZXJmb3JtYW5jZSBnZXRzIHdvcnNlIHdpdGggYWRkaXRpb25hbCBncm91cHMuCjMuIEctc3F1YXJlZCBzdGF0aXN0aWNzIC0gYW4gaW5jcmVhc2luZyBudW1iZXIgb2YgZ3JvdXBzIHByb2R1Y2VzIGJldHRlciBmaXR0aW5nIG1vZGVscywgYnV0IHRoZXJlIGlzIG5vIGNsZWFyIGtuZWUgcG9pbnQgbGlrZSB3aXRoIHRoZSBBSUMuIFJlbGF0aXZlIGltcHJvdmVtZW50cyBzbG93IGRvd24gYWZ0ZXIgNSBjbGFzc2VzLgo0LiBDaGktc3F1YXJlZCBzdGF0aXN0aWMgLSBBbnkgbW9kZWwgdGhhdCBpcyBub3QgYSAxIGNsYXNzIG1vZGVsIGlzIGEgbWFya2VkIGltcHJvdmVtZW50LiAKCkJhc2VkIG9uIHRoZXNlIG1ldHJpY3MsIGEgNSBjbGFzcyBzb2x1dGlvbiB3YXMgc2VsZWN0ZWQgYXMgdGhlIGZpbmFsIG1vZGVsLiBJIGhhdmUgaW5jbHVkZWQgdGhlIG1vZGVsIHN1bW1hcnkgYmVsb3cuIEl0IGluY2x1ZGVzIHRoZSBjb25kaXRpb25hbCBwcm9iYWJpbGl0aWVzIG9mIGVhY2ggY2xhc3MgKGkuZS4gdGhlaXIgbWVhbiBjaGFyYWN0ZXJpc3RpY3Mgb2YgZWFjaCBpbnB1dCB2YXJpYWJsZSkgYW5kIHRoZWlyIGNsYXNzIHByZXZhbGVuY2UgKGkuZS4gaG93IGJpZyB0aGV5IGFyZSkuIEFsc28gaW5jbHVkZWQgaXMgdGhlIHdob2xlIHNhbXBsZSBhdmVyYWdlIGNoYXJhY3RlcmlzdGljcyB0byBhaWQgaW50ZXJwcmV0YXRpb24uCgpgYGB7cn0Kc291cmNlKCIuL3RpZHlfcG9MQ0FfcmVzdWx0cy5SIikgIyBGb3IgNSBjbGFzcyBzb2x1dGlvbiwgaWYgY2hhbmdlIG51bWJlciBvZiBjbGFzc2VzIHRoZW4gbmVlZCB0byBtYW51YWxseSBlZGl0CndyaXRlLmNzdihyZXN1bHRzLCAiLi9jb25kX3Byb2JfbmFpcm9iaS5jc3YiKSAjIFNhdmUKcmVzdWx0cwoKYGBgCgpPayBsZXQncyBoYXZlIGEgbG9vayBhdCB0aGUgY29uZGl0aW9uYWwgcHJvYmFiaWxpdGllcyBieSBkYXRhIGNhdGVnb3J5LgoKIyMjT3V0bGV0IFR5cGUKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShncmlkKQoKIyBSZXNoYXBlIHRoZSByZXN1bHRzIHRhYmxlIGludG8gZm9ybWF0IGZvciBnZ3Bsb3QKbGlicmFyeShyZXNoYXBlMikKaG9sZCA8LSByZXN1bHRzWzQ6MTEsXSAjIFRha2Ugb25seSBvdXRsZXQgdmFyaWFibGVzCnRlbXAgPC0gbWVsdCgoaG9sZCksIG5hLnJtPVRSVUUpICMgVHVybiBpbnRvIGxvbmcgZm9ybWF0CgojIFBvbGFyIHBsb3QKbmFpcm9iaV9sY2ExIDwtIGdncGxvdCh0ZW1wLCBhZXMoeD1WYWx1ZSwgeT12YWx1ZSwgZ3JvdXAgPSB2YXJpYWJsZSwgY29sb3VyPXZhcmlhYmxlKSkgKwogICAgICAgICAgICAgICAgICBnZW9tX2xpbmUoc2l6ZT0xLjIpICsgeWxpbSgwLDEpICsgIAogICAgICAgICAgICAgICAgICBjb29yZF9wb2xhcigpICsgbGFicyh4ID0gTlVMTCwgeSA9IE5VTEwsIGNvbG9yID0gIkxhdGVudCBDbGFzcyIpICsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwLCBoanVzdCA9IDEuNSwgc2l6ZSA9IDEwKSkgKwogICAgICAgICAgICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpICsgZ2d0aXRsZSgiT3V0bGV0IFR5cGVzIikgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKyBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MyIpICsgdGhlbWUoYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpKSArIHRoZW1lKHBsb3QubWFyZ2luPXVuaXQoYygwLjUsMiwwLjUsMiksImNtIikpICsgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSBjKCJiYXJfcHViIiA9ICJiYXIvcHViIiwgImxvY2FsX3ZlbmRvciIgPSAibG9jYWwgdmVuZG9yIiwgICJzdGFuZF90YWJsZV90b3AiID0gInRhYmxldG9wIiwgIm90aGVyX291dGxldCIgPSAib3RoZXIiKSkKbmFpcm9iaV9sY2ExX25vbGVnIDwtIG5haXJvYmlfbGNhMSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgIyBQbG90IHdpdGhvdXQgbGVnZW5kCgojIFBsb3QgYnV0IGhhdmUgbmFtZXMgb3ZlcmxhcApndF8xIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKG5haXJvYmlfbGNhMSkpICMgV2l0aCBsZWdlbmQKZ3RfMSRsYXlvdXQkY2xpcFtndF8xJGxheW91dCRuYW1lID09ICJwYW5lbCJdIDwtICJvZmYiCmdnc2F2ZSgiLi9QbG90cy9sY2Ffb3V0bGV0X3R5cGVfbmFpcm9iaS50aWZmIiwgcGxvdCA9IGd0XzEsIHNjYWxlID0gMSwgZHBpID0gMzAwKQpnZ3NhdmUoIi4vUGxvdHMgbG93IHJlcy9sY2Ffb3V0bGV0X3R5cGVfbmFpcm9iaS5qcGVnIiwgcGxvdCA9IGd0XzEsIGRwaSA9IDMwMCwgc2NhbGUgPSAxKQpwbG90KGd0XzEpCgpndF8xX25sIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKG5haXJvYmlfbGNhMV9ub2xlZykpICMgV2l0aG91dCBsZWdlbmQKZ3RfMV9ubCRsYXlvdXQkY2xpcFtndF8xX25sJGxheW91dCRuYW1lID09ICJwYW5lbCJdIDwtICJvZmYiCmdnc2F2ZSgiLi9QbG90cy9sY2Ffb3V0bGV0X3R5cGVfbmFpcm9iaV9ub2xlZy50aWZmIiwgcGxvdCA9IGd0XzFfbmwsIHNjYWxlID0gMSwgZHBpID0gMzAwKQpnZ3NhdmUoIi4vUGxvdHMgbG93IHJlcy9sY2Ffb3V0bGV0X3R5cGVfbmFpcm9iaV9ub2xlZy5qcGVnIiwgcGxvdCA9IGd0XzFfbmwsIGRwaSA9IDMwMCwgc2NhbGUgPSAxKQoKIyBGdW5jdGlvbiB0byBzdG9yZSBsZWdlbmQKZ2V0X2xlZ2VuZDwtZnVuY3Rpb24obXlnZ3Bsb3QpewogIHRtcCA8LSBnZ3Bsb3RfZ3RhYmxlKGdncGxvdF9idWlsZChteWdncGxvdCkpCiAgbGVnIDwtIHdoaWNoKHNhcHBseSh0bXAkZ3JvYnMsIGZ1bmN0aW9uKHgpIHgkbmFtZSkgPT0gImd1aWRlLWJveCIpCiAgbGVnZW5kIDwtIHRtcCRncm9ic1tbbGVnXV0KICByZXR1cm4obGVnZW5kKQp9CgpsZWdlbmQgPC0gZ2V0X2xlZ2VuZChuYWlyb2JpX2xjYTEpICMgU3RvcmUgbGVnZW5kCgpgYGAKCiMjIyBBZHZlcnQgVHlwZQoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdyaWQpCgojIFJlc2hhcGUgdGhlIHJlc3VsdHMgdGFibGUgaW50byBmb3JtYXQgZm9yIGdncGxvdApsaWJyYXJ5KHJlc2hhcGUyKQpob2xkIDwtIHJlc3VsdHNbYygxOjMsIDEyOjE1KSxdICMgVGFrZSBvbmx5IG91dGxldCB2YXJpYWJsZXMKdGVtcCA8LSBtZWx0KChob2xkKSwgbmEucm09VFJVRSkgIyBUdXJuIGludG8gbG9uZyBmb3JtYXQKCiMgUG9sYXIgcGxvdApuYWlyb2JpX2xjYTFhIDwtIGdncGxvdCh0ZW1wLCBhZXMoeD1WYWx1ZSwgeT12YWx1ZSwgZ3JvdXAgPSB2YXJpYWJsZSwgY29sb3VyPXZhcmlhYmxlKSkgKwogICAgICAgICAgICAgICAgICBnZW9tX2xpbmUoc2l6ZT0xLjIpICsgeWxpbSgwLDEpICsgIAogICAgICAgICAgICAgICAgICBjb29yZF9wb2xhcigpICsgbGFicyh4ID0gTlVMTCwgeSA9IE5VTEwsIGNvbG9yID0gIkxhdGVudCBDbGFzcyIpICsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwLCBoanVzdCA9IDEuNSwgc2l6ZSA9IDEwKSkgKwogICAgICAgICAgICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpICsgZ2d0aXRsZSgiQWR2ZXJ0IFR5cGVzIikgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKyBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MyIpICsgdGhlbWUoYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpKSArIHRoZW1lKHBsb3QubWFyZ2luPXVuaXQoYygwLjUsMiwwLjUsMiksImNtIikpICsgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSBjKCJiaWxsYm9hcmRfYWR2IiA9ICJiaWxsYm9hcmQgYWR2ZXJ0IiwgIm9uc2l0ZV9hZHYiID0gIm9uc2l0ZSBhZHZlcnQiLCAicG9zdGVyX2FkdiIgPSAicG9zdGVyIGFkdmVydCIsICJvdXRsZXRfbm9fYWR2ZXJ0IiA9ICJvdXRsZXQgbm8gYWR2ZXJ0IiwgIm91dGxldF93X2FkdmVydCI9ICJvdXRsZXQgd2l0aCBhZHZlcnQiLCAicGFpbnRpbmdfYWR2IiA9ICJwYWludGluZyIsICJhZHZlcnRfb25seSIgPSAiYWR2ZXJ0IikpCm5haXJvYmlfbGNhMV9ub2xlZ2EgPC0gbmFpcm9iaV9sY2ExYSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgIyBQbG90IHdpdGhvdXQgbGVnZW5kCgojIFBsb3QgYnV0IGhhdmUgbmFtZXMgb3ZlcmxhcApndF8xYSA8LSBnZ3Bsb3RfZ3RhYmxlKGdncGxvdF9idWlsZChuYWlyb2JpX2xjYTFhKSkgIyBXaXRoIGxlZ2VuZApndF8xYSRsYXlvdXQkY2xpcFtndF8xYSRsYXlvdXQkbmFtZSA9PSAicGFuZWwiXSA8LSAib2ZmIgpnZ3NhdmUoIi4vUGxvdHMvbGNhX2FkdmVydF90eXBlX25haXJvYmkudGlmZiIsIHBsb3QgPSBndF8xYSwgc2NhbGUgPSAxLCBkcGkgPSAzMDApCmdnc2F2ZSgiLi9QbG90cyBsb3cgcmVzL2xjYV9hZHZlcnRfdHlwZV9uYWlyb2JpLmpwZWciLCBwbG90ID0gZ3RfMWEsIGRwaSA9IDMwMCwgc2NhbGUgPSAxKQpwbG90KGd0XzFhKQoKZ3RfMV9ubGEgPC0gZ2dwbG90X2d0YWJsZShnZ3Bsb3RfYnVpbGQobmFpcm9iaV9sY2ExX25vbGVnYSkpICMgV2l0aG91dCBsZWdlbmQKZ3RfMV9ubGEkbGF5b3V0JGNsaXBbZ3RfMV9ubGEkbGF5b3V0JG5hbWUgPT0gInBhbmVsIl0gPC0gIm9mZiIKZ2dzYXZlKCIuL1Bsb3RzL2xjYV9hZHZlcnRfdHlwZV9uYWlyb2JpX25vbGVnLnRpZmYiLCBwbG90ID0gZ3RfMV9ubGEsIHNjYWxlID0gMSwgZHBpID0gMzAwKQpnZ3NhdmUoIi4vUGxvdHMgbG93IHJlcy9sY2FfYWR2ZXJ0X3R5cGVfbmFpcm9iaV9ub2xlZy5qcGVnIiwgcGxvdCA9IGd0XzFfbmxhLCBkcGkgPSAzMDAsIHNjYWxlID0gMSkKCgpgYGAKCiMjI0Zvb2QgYmVpbmcgc29sZAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBSZXNoYXBlIHRoZSByZXN1bHRzIHRhYmxlIGludG8gZm9ybWF0IGZvciBnZ3Bsb3QKaG9sZCA8LSByZXN1bHRzWzE2OjQxLF0gIyBUYWtlIG9ubHkgb3V0bGV0IHZhcmlhYmxlcwp0ZW1wIDwtIG1lbHQoKGhvbGQpLCBuYS5ybT1UUlVFKSAjIFR1cm4gaW50byBsb25nIGZvcm1hdAoKIyBQb2xhciBwbG90Cm5haXJvYmlfbGNhMiA8LSBnZ3Bsb3QodGVtcCwgYWVzKHg9VmFsdWUsIHk9dmFsdWUsIGdyb3VwID0gdmFyaWFibGUsIGNvbG91cj12YXJpYWJsZSkpICsKICAgICAgICAgICAgICAgICAgZ2VvbV9saW5lKHNpemU9MS4yKSArIHlsaW0oMCwxKSArICAKICAgICAgICAgICAgICAgICAgY29vcmRfcG9sYXIoKSArIGxhYnMoeCA9IE5VTEwsIHkgPSBOVUxMLCBjb2xvciA9ICJMYXRlbnQgQ2xhc3MiKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCwgaGp1c3QgPSAxLjUsIHNpemUgPSAxMCkpICsKICAgICAgICAgICAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArIGdndGl0bGUoIkZvb2QgU29sZCIpICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDMiKSArIHRoZW1lKGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSkgKyB0aGVtZShwbG90Lm1hcmdpbj11bml0KGMoMC41LDIsMC41LDIpLCJjbSIpKSArIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gYygiZmF0c19vaWxzIiA9ICJmYXRzL29pbHMiLCAiZnJlc2hfZmlzaF9zaGVsbGZpc2giID0gImZyZXNoIGZpc2giLCAiY2FrZXNfc3dlZXRzIiA9ICJjYWtlcy9zd2VldHMiLCAiZnJlc2hfbWVhdF9wb3VsdHJ5IiA9ICJmcmVzaCBtZWF0IiwgImZyaWVkX3Jvb3RzX3R1YmVyc19wbG50bl9wb3RzIiA9ICJmcmllZCByb290IHZlZy4iLCAiZ3JhaW5fY2VyZWFsIiA9ICJncmFpbi9jZXJlYWwiLCAibGVndW1lc19wdWxzZXMiID0gImxlZ3VtZXMvcHVsc2VzIiwgIm1vZGVybl9taXhlZF9kaXNoZXMiID0gIm0uZGlzaCIsICJudXRzX3NlZWRzIj0gIm51dHMvc2VlZHMiLCAicHJvY3NzZF9mcmllZF9maXNoIiA9ICJwcm9jZXNzZWQgZmlzaCIsICJwcm9jc3NkX2ZyaWVkX21lYXRfcG91bHRyeSIgPSAicHJvY2Vzc2VkIG1lYXQiLCAic2F2b3VyeV9zbmFja3NfcGllcyIgPSAic2F2b3VyeSBzbmFja3MiLCAic29kYXNfc3dlZXRlbmVkX2JldnMiID0gInN3ZWV0ZW5kIGRyaW5rcyIsICJzb3Vwc19zdGV3cyI9ICJzb3Vwcy9zdGV3cyIsICJzdWdhcl9zd2VldF9zcHJlYWRzIiA9ICJzd2VldGVuZWQgc3ByZWFkcyIsICJ0ZWFfY29mZmVlIiA9ICJ0ZWEvY29mZmVlIiwgInRyYWRfbWl4ZWRfZGlzaGVzIiA9ICJ0cmFkLiBkaXNoZXMiLCAidmVnZXRhYmxlcyIgPSAidmVnLiIsICJub25mcmllZF9yb290c190dWJlcnNfcGxudG5fcG90cyIgPSAicm9vdCB2ZWcuIiwgImZyZXNoX2p1aWNlcyIgPSAiZnJlc2gganVpY2VzIikpCm5haXJvYmlfbGNhMl9ub2xlZyA8LSBuYWlyb2JpX2xjYTIgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICMgUGxvdCB3aXRob3V0IGxlZ2VuZAoKIyBQbG90IGJ1dCBoYXZlIG5hbWVzIG92ZXJsYXAKZ3RfMiA8LSBnZ3Bsb3RfZ3RhYmxlKGdncGxvdF9idWlsZChuYWlyb2JpX2xjYTIpKSAjIFdpdGggbGVnZW5kCmd0XzIkbGF5b3V0JGNsaXBbZ3RfMiRsYXlvdXQkbmFtZSA9PSAicGFuZWwiXSA8LSAib2ZmIgpnZ3NhdmUoIi4vUGxvdHMvbGNhX2Zvb2Rfc29sZF9uYWlyb2JpLnRpZmYiLCBwbG90ID0gZ3RfMiwgc2NhbGUgPSAxLCBkcGkgPSAzMDApCmdnc2F2ZSgiLi9QbG90cyBsb3cgcmVzL2xjYV9mb29kX3NvbGRfbmFpcm9iaS5qcGVnIiwgcGxvdCA9IGd0XzIsIGRwaSA9IDMwMCwgc2NhbGUgPSAxKQoKcGxvdChndF8yKQoKZ3RfMl9ubCA8LSBnZ3Bsb3RfZ3RhYmxlKGdncGxvdF9idWlsZChuYWlyb2JpX2xjYTJfbm9sZWcpKSAjIFdpdGhvdXQgbGVnZW5kCmd0XzJfbmwkbGF5b3V0JGNsaXBbZ3RfMl9ubCRsYXlvdXQkbmFtZSA9PSAicGFuZWwiXSA8LSAib2ZmIgpnZ3NhdmUoIi4vUGxvdHMvbGNhX2Zvb2Rfc29sZF9uYWlyb2JpX25vbGVnLnRpZmYiLCBwbG90ID0gZ3RfMl9ubCwgc2NhbGUgPSAxLCBkcGkgPSAzMDApCmdnc2F2ZSgiLi9QbG90cyBsb3cgcmVzL2xjYV9mb29kX3NvbGRfbmFpcm9iaV9ub2xlZy5qcGVnIiwgcGxvdCA9IGd0XzJfbmwsIGRwaSA9IDMwMCwgc2NhbGUgPSAxKQoKYGBgCgojIyNGb29kIGJlaW5nIGFkdmVydGlzZWQKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgUmVzaGFwZSB0aGUgcmVzdWx0cyB0YWJsZSBpbnRvIGZvcm1hdCBmb3IgZ2dwbG90CmhvbGQgPC0gcmVzdWx0c1s0Mjo2NSxdICMgVGFrZSBvbmx5IG91dGxldCB2YXJpYWJsZXMKdGVtcCA8LSBtZWx0KChob2xkKSwgbmEucm09VFJVRSkgIyBUdXJuIGludG8gbG9uZyBmb3JtYXQKCiMgUG9sYXIgcGxvdApuYWlyb2JpX2xjYTMgPC0gZ2dwbG90KHRlbXAsIGFlcyh4PVZhbHVlLCB5PXZhbHVlLCBncm91cCA9IHZhcmlhYmxlLCBjb2xvdXI9dmFyaWFibGUpKSArCiAgICAgICAgICAgICAgICAgIGdlb21fbGluZShzaXplPTEuMikgKyB5bGltKDAsMSkgKyAgCiAgICAgICAgICAgICAgICAgIGNvb3JkX3BvbGFyKCkgKyBsYWJzKHggPSBOVUxMLCB5ID0gTlVMTCwgY29sb3IgPSAiTGF0ZW50IENsYXNzIikgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsIGhqdXN0ID0gMS41LCBzaXplID0gMTApKSArCiAgICAgICAgICAgICAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikgKyBnZ3RpdGxlKCJGb29kIEFkdmVydGlzZWQiKSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQzIikgKyB0aGVtZShheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MueT1lbGVtZW50X2JsYW5rKCkpICsgdGhlbWUocGxvdC5tYXJnaW49dW5pdChjKDAuNSwyLDAuNSwyKSwiY20iKSkgKyBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGMoImZhdHNfb2lscyIgPSAiZmF0cy9vaWxzIiwgImZyZXNoX2Zpc2hfc2hlbGxmaXNoIiA9ICJmcmVzaCBmaXNoIiwgImNha2VzX3N3ZWV0cyIgPSAiY2FrZXMvc3dlZXRzIiwgImZyZXNoX21lYXRfcG91bHRyeSIgPSAiZnJlc2ggbWVhdCIsICJmcmllZF9yb290c190dWJlcnNfcGxudG5fcG90cyIgPSAiZnJpZWQgcm9vdCB2ZWcuIiwgImdyYWluX2NlcmVhbCIgPSAiZ3JhaW4vY2VyZWFsIiwgImxlZ3VtZXNfcHVsc2VzIiA9ICJsZWd1bWVzL3B1bHNlcyIsICJtb2Rlcm5fbWl4ZWRfZGlzaGVzIiA9ICJtLmRpc2giLCAibnV0c19zZWVkcyI9ICJudXRzL3NlZWRzIiwgInByb2Nzc2RfZnJpZWRfZmlzaCIgPSAicHJvY2Vzc2VkIGZpc2giLCAicHJvY3NzZF9mcmllZF9tZWF0X3BvdWx0cnkiID0gInByb2Nlc3NlZCBtZWF0IiwgInNhdm91cnlfc25hY2tzX3BpZXMiID0gInNhdm91cnkgc25hY2tzIiwgInNvZGFzX3N3ZWV0ZW5lZF9iZXZzIiA9ICJzd2VldGVuZCBkcmlua3MiLCAic291cHNfc3Rld3MiPSAic291cHMvc3Rld3MiLCAic3VnYXJfc3dlZXRfc3ByZWFkcyIgPSAic3dlZXRlbmVkIHNwcmVhZHMiLCAidGVhX2NvZmZlZSIgPSAidGVhL2NvZmZlZSIsICJ0cmFkX21peGVkX2Rpc2hlcyIgPSAidHJhZC4gZGlzaGVzIiwgInZlZ2V0YWJsZXMiID0gInZlZy4iKSkKbmFpcm9iaV9sY2EzX25vbGVnIDwtIG5haXJvYmlfbGNhMyArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgIyBQbG90IHdpdGhvdXQgbGVnZW5kCgojIFBsb3QgYnV0IGhhdmUgbmFtZXMgb3ZlcmxhcApndF8zIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKG5haXJvYmlfbGNhMykpICMgV2l0aCBsZWdlbmQKZ3RfMyRsYXlvdXQkY2xpcFtndF8zJGxheW91dCRuYW1lID09ICJwYW5lbCJdIDwtICJvZmYiCmdnc2F2ZSgiLi9QbG90cy9sY2FfZm9vZF9hZHZfbmFpcm9iaS50aWZmIiwgcGxvdCA9IGd0XzMsIHNjYWxlID0gMSwgZHBpID0gMzAwKQpnZ3NhdmUoIi4vUGxvdHMgbG93IHJlcy9sY2FfZm9vZF9hZHZfbmFpcm9iaS5qcGVnIiwgcGxvdCA9IGd0XzMsIGRwaSA9IDMwMCwgc2NhbGUgPSAxKQoKcGxvdChndF8zKQoKZ3RfM19ubCA8LSBnZ3Bsb3RfZ3RhYmxlKGdncGxvdF9idWlsZChuYWlyb2JpX2xjYTNfbm9sZWcpKSAjIFdpdGhvdXQgbGVnZW5kCmd0XzNfbmwkbGF5b3V0JGNsaXBbZ3RfM19ubCRsYXlvdXQkbmFtZSA9PSAicGFuZWwiXSA8LSAib2ZmIgpnZ3NhdmUoIi4vUGxvdHMvbGNhX2Zvb2RfYWR2X25haXJvYmlfbm9sZWcudGlmZiIsIHBsb3QgPSBndF8zX25sLCBzY2FsZSA9IDEsIGRwaSA9IDMwMCkKZ2dzYXZlKCIuL1Bsb3RzIGxvdyByZXMvbGNhX2Zvb2RfYWR2X25haXJvYmlfbm9sZWcuanBlZyIsIHBsb3QgPSBndF8zX25sLCBkcGkgPSAzMDAsIHNjYWxlID0gMSkKCmBgYAoKTGV0J3Mgam9pbiB0aGVtIHRvZ2V0aGVyIGludG8gYSBzaW5nbGUgcGxvdC4KCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoZ3JpZEV4dHJhKQojIENyZWF0ZSBibGFuayBwbG90IHRvIGNlbnRyZSBsZWdlbmQKYmxhbmtQbG90IDwtIGdncGxvdCgpK2dlb21fYmxhbmsoYWVzKDEsMSkpICsgCiAgY293cGxvdDo6dGhlbWVfbm90aGluZygpCgojIEpvaW4gdG9nZXRoZXIgcGxvdHMgaW50byBzaW5nbGUgcGxvdAojIFNhdmUgYXMgUERGCnBkZigiLi9QbG90cy9uYWlyb2JpX2FsbF9wbG90cy5wZGYiLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSAxMCkgCmdyaWQuYXJyYW5nZShndF8xX25sLCBndF8xX25sYSwgZ3RfMl9ubCwgZ3RfM19ubCwgbGVnZW5kLCBuY29sID0gMiwgbnJvdyA9IDMsCiAgICAgICAgICAgICAgICAgICAgICB3aWR0aHMgPSBjKDEwLCAxMCksIGhlaWdodHMgPSBjKDEwLCAxMCwgNCkpCmRldi5vZmYoKQoKIyBTYXZlIGFzIGltYWdlL3RpZmYgZmlsZQp0aWZmKCIuL1Bsb3RzL25haXJvYmlfYWxsX3Bsb3RzLnRpZmYiLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSAxMCwgdW5pdHMgPSAiaW4iLCByZXMgPSAzMDApCmdyaWQuYXJyYW5nZShndF8xX25sLCBndF8xX25sYSwgZ3RfMl9ubCwgZ3RfM19ubCwgbGVnZW5kLCBuY29sID0gMiwgbnJvdyA9IDMsCiAgICAgICAgICAgICAgICAgICAgICB3aWR0aHMgPSBjKDEwLCAxMCksIGhlaWdodHMgPSBjKDEwLCAxMCwgNCkpCmRldi5vZmYoKQoKYGBgCgojQWNjcmEsIEdoYW5hCgpGaXJzdCwgd2UgYXNzZXNzIGhvdyBtYW55IGxhdGVudCBjbGFzc2VzLgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBTdWJzZXQgQWNjcmEgZGF0YSBvbmx5CmFjY3JhIDwtIGdoYW5hW2doYW5hJGxvY2F0aW9uID09ICJBY2NyYSJdCgojIERlZmluZSB2YXJpYWJsZXMgdG8gYmUgdXNlZCBpbiBMQ0EgdG8gZXN0aW1hdGUgZ3JvdXBzICh0b28gbWFueSB2YXJpYWJsZXM/KQpmIDwtIHdpdGgoYWNjcmEsIAogICAgICAgICAgY2JpbmQoIyBUeXBlIG9mIG91dGxldCAocmVzdGF1cmFudCwgc29jaWFsIG1hcmtldGluZyBhbmQgYmlsbGJvYXJkcyBkcm9wcGVkIGFzIG5vbmUpCiAgICAgICAgICAgb3V0bGV0X3dfYWR2ZXJ0LCBvdXRsZXRfbm9fYWR2ZXJ0LCBhZHZlcnRfb25seSwgc3VwZXJtYXJrZXQsIHNob3AsIGtpb3NrLCBzdGFuZF90YWJsZV90b3AsIGxvY2FsX3ZlbmRvciwgYmFyX3B1Yiwgb3RoZXJfb3V0bGV0LCBwb3N0ZXJfYWR2LCBvbnNpdGVfYWR2LCBwYWludGluZ19hZHYsCiAgICAgICAgICAgIyBGb29kcyBzb2xkCiAgICAgICAgICAgZ3JhaW5fY2VyZWFsLCBmcmVzaF9tZWF0X3BvdWx0cnksIGZyZXNoX2Zpc2hfc2hlbGxmaXNoLCBwcm9jc3NkX2ZyaWVkX21lYXRfcG91bHRyeSwgcHJvY3NzZF9mcmllZF9maXNoLCB0cmFkX21peGVkX2Rpc2hlcywgbW9kZXJuX21peGVkX2Rpc2hlcywgc291cHNfc3Rld3MsIGZyaWVkX3Jvb3RzX3R1YmVyc19wbG50bl9wb3RzLCBub25mcmllZF9yb290c190dWJlcnNfcGxudG5fcG90cywgZnJ1aXRzLCB2ZWdldGFibGVzLCBjYWtlc19zd2VldHMsIHNhdm91cnlfc25hY2tzX3BpZXMsIHNvZGFzX3N3ZWV0ZW5lZF9iZXZzLCBtaWxrLCBmcmVzaF9qdWljZXMsIGFsY29ob2wsIHN1Z2FyX3N3ZWV0X3NwcmVhZHMsIHRlYV9jb2ZmZWUsIGZhdHNfb2lscywgbnV0c19zZWVkcywgbGVndW1lc19wdWxzZXMsIGNvbmRpbWVudHMsIGVnZ3MsIG90aGVyLAogICAgICAgICAgICMgQWR2ZXJ0aXNlbWVudHMgKHRlYS9jb2ZmZWUgMCBzbyBkcm9wcGVkLCBhcyB3YXMgbnV0cy9zZWVkcyBhbmQgYWR2ZXJ0IG90aGVyKQogICAgICAgICAgIGFkdl9ncmFpbl9jZXJlYWwsIGFkdl9mcmVzaF9tZWF0X3BvdWx0cnksIGFkdl9mcmVzaF9maXNoX3NoZWxsZmlzaCwgYWR2X3Byb2Nzc2RfZnJpZWRfbWVhdF9wb3VsdHJ5LCBhZHZfcHJvY3NzZF9mcmllZF9maXNoLCBhZHZfdHJhZF9taXhlZF9kaXNoZXMsIGFkdl9tb2Rlcm5fbWl4ZWRfZGlzaGVzLCBhZHZfc291cHNfc3Rld3MsIGFkdl9mcmllZF9yb290c190dWJlcnNfcGxudG5fcG90cywgYWR2X25vbmZyaWVkX3Jvb3RzX3R1YmVyc19wbG50bl9wb3RzLCBhZHZfZnJ1aXRzLCBhZHZfdmVnZXRhYmxlcywgYWR2X2Nha2VzX3N3ZWV0cywgYWR2X3Nhdm91cnlfc25hY2tzX3BpZXMsIGFkdl9zb2Rhc19zd2VldGVuZWRfYmV2cywgYWR2X21pbGssIGFkdl9mcmVzaF9qdWljZXMsIGFkdl9hbGNvaG9sLCBhZHZfc3VnYXJfc3dlZXRfc3ByZWFkcywgYWR2X2ZhdHNfb2lscywgYWR2X2xlZ3VtZXNfcHVsc2VzLCBhZHZfY29uZGltZW50cywgYWR2X2VnZ3MpfjEpCgojIElkZW50aWZ5IGJlc3QgbnVtYmVyIG9mIGdyb3VwcwoKbnVtYmVycyA8LSBjKDE6MTApCgpmb3IgKGkgaW4gbnVtYmVycykgewogIHRlbXAgPC0gcG9MQ0EoZiwgYWNjcmEsIG5jbGFzcz1pLCBucmVwPTIwLCBtYXhpdGVyPTEwMDAwMCwgdmVyYm9zZT1GQUxTRSwgbmEucm09VCkKICBhc3NpZ24ocGFzdGUwKCJsY2FfYWxsIixpKSwgdGVtcCkKICBybSh0ZW1wKQp9CgojIENvbXBhcmUgc29sdXRpb25zCkFJQyA8LSBjKHJiaW5kKGxjYV9hbGwxJGFpYywgbGNhX2FsbDIkYWljLCBsY2FfYWxsMyRhaWMsIGxjYV9hbGw0JGFpYywgbGNhX2FsbDUkYWljLAogICAgICAgICAgICAgICBsY2FfYWxsNiRhaWMsIGxjYV9hbGw3JGFpYywgbGNhX2FsbDgkYWljLCBsY2FfYWxsOSRhaWMsIGxjYV9hbGwxMCRhaWMpKQpCSUMgPC0gYyhyYmluZChsY2FfYWxsMSRiaWMsIGxjYV9hbGwyJGJpYywgbGNhX2FsbDMkYmljLCBsY2FfYWxsNCRiaWMsIGxjYV9hbGw1JGJpYywKICAgICAgICAgICAgICAgbGNhX2FsbDYkYmljLCBsY2FfYWxsNyRiaWMsIGxjYV9hbGw4JGJpYywgbGNhX2FsbDkkYmljLCBsY2FfYWxsMTAkYmljKSkKR3NxIDwtIGMocmJpbmQobGNhX2FsbDEkR3NxLCBsY2FfYWxsMiRHc3EsIGxjYV9hbGwzJEdzcSwgbGNhX2FsbDQkR3NxLCBsY2FfYWxsNSRHc3EsCiAgICAgICAgICAgICAgIGxjYV9hbGw2JEdzcSwgbGNhX2FsbDckR3NxLCBsY2FfYWxsOCRHc3EsIGxjYV9hbGw5JEdzcSwgbGNhX2FsbDEwJEdzcSkpCkNoaXNxIDwtIGMocmJpbmQobGNhX2FsbDEkQ2hpc3EsIGxjYV9hbGwyJENoaXNxLCBsY2FfYWxsMyRDaGlzcSwgbGNhX2FsbDQkQ2hpc3EsIGxjYV9hbGw1JENoaXNxLAogICAgICAgICAgICAgICAgIGxjYV9hbGw2JENoaXNxLCBsY2FfYWxsNyRDaGlzcSwgbGNhX2FsbDgkQ2hpc3EsIGxjYV9hbGw5JENoaXNxLCBsY2FfYWxsMTAkQ2hpc3EpKQpHcm91cHMgPC0gYygxOjEwKQpudW1iX2dycHNfYWxsIDwtIGNiaW5kKEdyb3VwcyxBSUMsQklDLEdzcSxDaGlzcSkgIyBQdXQgdG9nZXRoZXIgaW4gb25lIHRhYmxlCndyaXRlLnRhYmxlKG51bWJfZ3Jwc19hbGwsICIuL251bWJlcl9vZl9ncm91cHNfYWNjcmEudHh0Iiwgc2VwID0gIlx0Iiwgcm93Lm5hbWVzID0gRkFMU0UpICMgU2F2ZQoKIyBQbG90IHZhbHVlcwpudW1iX2dycHNfYWxsIDwtIGFzLmRhdGEuZnJhbWUobnVtYl9ncnBzX2FsbCkKcGxvdDEgPC0gZ2dwbG90KG51bWJfZ3Jwc19hbGwsIGFlcyh4ID0gR3JvdXBzLCB5ID0gQUlDKSkgKyBnZW9tX3BvaW50KCkgKyB4bGFiKCJOdW1iZXIgb2YgY2xhc3NlcyIpICsgeWxhYigiQWthaWtlIEluZm9ybWF0aW9uIENyaXRlcmlvbiIpICsgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKDAsIDEwKSwgYnJlYWtzID0gc2VxKDAsMTAsMikpCmdnc2F2ZSgiLi9QbG90cy9hY2NyYV9sY2FfYWljLnRpZmYiLCBwbG90ID0gcGxvdDEsIGRwaSA9IDMwMCwgd2lkdGggPSA3LCBoZWlnaHQgPSA3KQpnZ3NhdmUoIi4vUGxvdHMgbG93IHJlcy9hY2NyYV9sY2FfYWljLmpwZWciLCBwbG90ID0gcGxvdDEsIGRwaSA9IDMwMCwgd2lkdGggPSA3LCBoZWlnaHQgPSA3KQpwbG90MQoKcGxvdDIgPC0gZ2dwbG90KG51bWJfZ3Jwc19hbGwsIGFlcyh4ID0gR3JvdXBzLCB5ID0gQklDKSkgKyBnZW9tX3BvaW50KCkgKyB4bGFiKCJOdW1iZXIgb2YgY2xhc3NlcyIpICsgeWxhYigiQmF5ZXNpYW4gSW5mb3JtYXRpb24gQ3JpdGVyaW9uIikgKyBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMCwgMTApLCBicmVha3MgPSBzZXEoMCwxMCwyKSkKZ2dzYXZlKCIuL1Bsb3RzL2FjY3JhX2xjYV9iaWMudGlmZiIsIHBsb3QgPSBwbG90MiwgZHBpID0gMzAwLCB3aWR0aCA9IDcsIGhlaWdodCA9IDcpCmdnc2F2ZSgiLi9QbG90cyBsb3cgcmVzL2FjY3JhX2xjYV9iaWMuanBlZyIsIHBsb3QgPSBwbG90MiwgZHBpID0gMzAwLCB3aWR0aCA9IDcsIGhlaWdodCA9IDcpCnBsb3QyCgpwbG90MyA8LSBnZ3Bsb3QobnVtYl9ncnBzX2FsbCwgYWVzKHggPSBHcm91cHMsIHkgPSBHc3EpKSArIGdlb21fcG9pbnQoKSArIHhsYWIoIk51bWJlciBvZiBjbGFzc2VzIikgKyB5bGFiKCJHLXNxdWFyZWQgc3RhdGlzdGljIikgKyBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMCwgMTApLCBicmVha3MgPSBzZXEoMCwxMCwyKSkKZ2dzYXZlKCIuL1Bsb3RzL2FjY3JhX2xjYV9nc3EudGlmZiIsIHBsb3QgPSBwbG90MywgZHBpID0gMzAwLCB3aWR0aCA9IDcsIGhlaWdodCA9IDcpCmdnc2F2ZSgiLi9QbG90cyBsb3cgcmVzL2FjY3JhX2xjYV9nc3EuanBlZyIsIHBsb3QgPSBwbG90MywgZHBpID0gMzAwLCB3aWR0aCA9IDcsIGhlaWdodCA9IDcpCnBsb3QzCgpwbG90NCA8LSBnZ3Bsb3QobnVtYl9ncnBzX2FsbCwgYWVzKHggPSBHcm91cHMsIHkgPSBDaGlzcSkpICsgZ2VvbV9wb2ludCgpICsgeGxhYigiTnVtYmVyIG9mIGNsYXNzZXMiKSArIHlsYWIoIkNoaS1zcXVhcmVkIHN0YXRpc3RpYyIpICsgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKDAsIDEwKSwgYnJlYWtzID0gc2VxKDAsMTAsMikpCmdnc2F2ZSgiLi9QbG90cy9hY2NyYV9sY2FfY2hpc3EudGlmZiIsIHBsb3QgPSBwbG90NCwgZHBpID0gMzAwLCB3aWR0aCA9IDcsIGhlaWdodCA9IDcpCmdnc2F2ZSgiLi9QbG90cyBsb3cgcmVzL2FjY3JhX2xjYV9jaGlzcS5qcGVnIiwgcGxvdCA9IHBsb3Q0LCBkcGkgPSAzMDAsIHdpZHRoID0gNywgaGVpZ2h0ID0gNykKcGxvdDQKCmBgYAoKSG1tbSwgYSA1IGdyb3VwIHNvbHV0aW9uIHNlZW1zIGJlc3QgaGVyZSAtIHJvdWdobHkgd2hlcmUgaXQgbGV2ZWxzIG9mZiBvbiB0aHJlZSBvZiB0aGUgbWV0cmljcy4gVGhlIGZpbmFsIG9uZSBkb2Vzbid0IHJlYWxseSBoZWxwIHVzIGF0IGFsbC4gTGV0J3MgaGF2ZSBhIGxvb2sgYXQgdGhlIGNsdXN0ZXIgY2VudHJlcyBhbmQgc3RhcnQgaW50ZXJwcmV0aW5nIHRoZSBjbHVzdGVycy4KCmBgYHtyfQpzb3VyY2UoIi4vdGlkeV9wb0xDQV9yZXN1bHRzX2FjY3JhLlIiKSAjIEZvciA1IGNsYXNzIHNvbHV0aW9uLCBpZiBjaGFuZ2UgbnVtYmVyIG9mIGNsYXNzZXMgdGhlbiBuZWVkIHRvIG1hbnVhbGx5IGVkaXQKd3JpdGUuY3N2KHJlc3VsdHMsICIuL2NvbmRfcHJvYl9hY2NyYS5jc3YiKSAjIFNhdmUKcmVzdWx0cwpgYGAKCkkgd2lsbCBpbmNvcnBvcmF0ZSB0aGVpciBpbnRlcnByZXRhdGlvbiBpbiB0aGUgZm9sbG93aW5nIHNlY3Rpb25zIGJlbG93LgoKIyMjT3V0bGV0IFR5cGUKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShncmlkKQoKIyBSZXNoYXBlIHRoZSByZXN1bHRzIHRhYmxlIGludG8gZm9ybWF0IGZvciBnZ3Bsb3QKbGlicmFyeShyZXNoYXBlMikKaG9sZCA8LSByZXN1bHRzWzQ6MTAsXSAjIFRha2Ugb25seSBvdXRsZXQgdmFyaWFibGVzCnRlbXAgPC0gbWVsdCgoaG9sZCksIG5hLnJtPVRSVUUpICMgVHVybiBpbnRvIGxvbmcgZm9ybWF0CgojIFBvbGFyIHBsb3QKYWNjcmFfbGNhMSA8LSBnZ3Bsb3QodGVtcCwgYWVzKHg9VmFsdWUsIHk9dmFsdWUsIGdyb3VwID0gdmFyaWFibGUsIGNvbG91cj12YXJpYWJsZSkpICsKICAgICAgICAgICAgICAgICAgZ2VvbV9saW5lKHNpemU9MS4yKSArIHlsaW0oMCwxKSArICAKICAgICAgICAgICAgICAgICAgY29vcmRfcG9sYXIoKSArIGxhYnMoeCA9IE5VTEwsIHkgPSBOVUxMLCBjb2xvciA9ICJMYXRlbnQgQ2xhc3MiKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCwgaGp1c3QgPSAxLjUsIHNpemUgPSAxMCkpICsKICAgICAgICAgICAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArIGdndGl0bGUoIk91dGxldCBUeXBlcyIpICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDMiKSArIHRoZW1lKGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSkgKyB0aGVtZShwbG90Lm1hcmdpbj11bml0KGMoMC41LDIsMC41LDIpLCJjbSIpKSArIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gYygiYmFyX3B1YiIgPSAiYmFyL3B1YiIsICJiaWxsYm9hcmRfYWR2IiA9ICJiaWxsYm9hcmQgYWR2LiIsICJsb2NhbF92ZW5kb3IiID0gImxvY2FsIHZlbmRvciIsICJvbnNpdGVfYWR2IiA9ICJvbnNpdGUgYWR2LiIsICJzdGFuZF90YWJsZV90b3AiID0gInRhYmxldG9wIiwgIm90aGVyX291dGxldCIgPSAib3RoZXIgb3V0bGV0IikpCmFjY3JhX2xjYTFfbm9sZWcgPC0gYWNjcmFfbGNhMSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgIyBQbG90IHdpdGhvdXQgbGVnZW5kCgojIFBsb3QgYnV0IGhhdmUgbmFtZXMgb3ZlcmxhcApndF8xIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKGFjY3JhX2xjYTEpKSAjIFdpdGggbGVnZW5kCmd0XzEkbGF5b3V0JGNsaXBbZ3RfMSRsYXlvdXQkbmFtZSA9PSAicGFuZWwiXSA8LSAib2ZmIgpnZ3NhdmUoIi4vUGxvdHMvbGNhX291dGxldF90eXBlX2FjY3JhLnRpZmYiLCBwbG90ID0gZ3RfMSwgc2NhbGUgPSAxLCBkcGkgPSAzMDApCmdnc2F2ZSgiLi9QbG90cyBsb3cgcmVzL2xjYV9vdXRsZXRfdHlwZV9hY2NyYS5qcGVnIiwgcGxvdCA9IGd0XzEsIGRwaSA9IDMwMCwgc2NhbGUgPSAxKQpwbG90KGd0XzEpCgpndF8xX25sIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKGFjY3JhX2xjYTFfbm9sZWcpKSAjIFdpdGhvdXQgbGVnZW5kCmd0XzFfbmwkbGF5b3V0JGNsaXBbZ3RfMV9ubCRsYXlvdXQkbmFtZSA9PSAicGFuZWwiXSA8LSAib2ZmIgpnZ3NhdmUoIi4vUGxvdHMvbGNhX291dGxldF90eXBlX2FjY3JhX25vbGVnLnRpZmYiLCBwbG90ID0gZ3RfMV9ubCwgc2NhbGUgPSAxLCBkcGkgPSAzMDApCmdnc2F2ZSgiLi9QbG90cyBsb3cgcmVzL2xjYV9vdXRsZXRfdHlwZV9hY2NyYV9ub2xlZy5qcGVnIiwgcGxvdCA9IGd0XzFfbmwsIGRwaSA9IDMwMCwgc2NhbGUgPSAxKQoKIyBGdW5jdGlvbiB0byBzdG9yZSBsZWdlbmQKZ2V0X2xlZ2VuZDwtZnVuY3Rpb24obXlnZ3Bsb3QpewogIHRtcCA8LSBnZ3Bsb3RfZ3RhYmxlKGdncGxvdF9idWlsZChteWdncGxvdCkpCiAgbGVnIDwtIHdoaWNoKHNhcHBseSh0bXAkZ3JvYnMsIGZ1bmN0aW9uKHgpIHgkbmFtZSkgPT0gImd1aWRlLWJveCIpCiAgbGVnZW5kIDwtIHRtcCRncm9ic1tbbGVnXV0KICByZXR1cm4obGVnZW5kKQp9CgpsZWdlbmQgPC0gZ2V0X2xlZ2VuZChhY2NyYV9sY2ExKSAjIFN0b3JlIGxlZ2VuZAoKYGBgCgojIyMgQWR2ZXJ0IFR5cGUKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShncmlkKQoKIyBSZXNoYXBlIHRoZSByZXN1bHRzIHRhYmxlIGludG8gZm9ybWF0IGZvciBnZ3Bsb3QKbGlicmFyeShyZXNoYXBlMikKaG9sZCA8LSByZXN1bHRzW2MoMTozLCAxMToxMyksXSAjIFRha2Ugb25seSBvdXRsZXQgdmFyaWFibGVzCnRlbXAgPC0gbWVsdCgoaG9sZCksIG5hLnJtPVRSVUUpICMgVHVybiBpbnRvIGxvbmcgZm9ybWF0CgojIFBvbGFyIHBsb3QKYWNjcmFfbGNhMWEgPC0gZ2dwbG90KHRlbXAsIGFlcyh4PVZhbHVlLCB5PXZhbHVlLCBncm91cCA9IHZhcmlhYmxlLCBjb2xvdXI9dmFyaWFibGUpKSArCiAgICAgICAgICAgICAgICAgIGdlb21fbGluZShzaXplPTEuMikgKyB5bGltKDAsMSkgKyAgCiAgICAgICAgICAgICAgICAgIGNvb3JkX3BvbGFyKCkgKyBsYWJzKHggPSBOVUxMLCB5ID0gTlVMTCwgY29sb3IgPSAiTGF0ZW50IENsYXNzIikgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsIGhqdXN0ID0gMS41LCBzaXplID0gMTApKSArCiAgICAgICAgICAgICAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikgKyBnZ3RpdGxlKCJBZHZlcnQgVHlwZXMiKSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQzIikgKyB0aGVtZShheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MueT1lbGVtZW50X2JsYW5rKCkpICsgdGhlbWUocGxvdC5tYXJnaW49dW5pdChjKDAuNSwyLDAuNSwyKSwiY20iKSkgKyBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGMoImJpbGxib2FyZF9hZHYiID0gImJpbGxib2FyZCBhZHZlcnQiLCAib25zaXRlX2FkdiIgPSAib25zaXRlIGFkdmVydCIsICJwb3N0ZXJfYWR2IiA9ICJwb3N0ZXIgYWR2ZXJ0IiwgIm91dGxldF9ub19hZHZlcnQiID0gIm91dGxldCBubyBhZHZlcnQiLCAib3V0bGV0X3dfYWR2ZXJ0Ij0gIm91dGxldCB3aXRoIGFkdmVydCIsICJwYWludGluZ19hZHYiID0gInBhaW50aW5nIiwgImFkdmVydF9vbmx5IiA9ICJhZHZlcnQiKSkKYWNjcmFfbGNhMWFfbm9sZWdhIDwtIGFjY3JhX2xjYTFhICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSAjIFBsb3Qgd2l0aG91dCBsZWdlbmQKCiMgUGxvdCBidXQgaGF2ZSBuYW1lcyBvdmVybGFwCmd0XzFhIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKGFjY3JhX2xjYTFhKSkgIyBXaXRoIGxlZ2VuZApndF8xYSRsYXlvdXQkY2xpcFtndF8xYSRsYXlvdXQkbmFtZSA9PSAicGFuZWwiXSA8LSAib2ZmIgpnZ3NhdmUoIi4vUGxvdHMvbGNhX2FkdmVydF90eXBlX2FjY3JhLnRpZmYiLCBwbG90ID0gZ3RfMWEsIHNjYWxlID0gMSwgZHBpID0gMzAwKQpnZ3NhdmUoIi4vUGxvdHMgbG93IHJlcy9sY2FfYWR2ZXJ0X3R5cGVfYWNjcmEuanBlZyIsIHBsb3QgPSBndF8xYSwgZHBpID0gMzAwLCBzY2FsZSA9IDEpCnBsb3QoZ3RfMWEpCgpndF8xX25sYSA8LSBnZ3Bsb3RfZ3RhYmxlKGdncGxvdF9idWlsZChhY2NyYV9sY2ExYV9ub2xlZ2EpKSAjIFdpdGhvdXQgbGVnZW5kCmd0XzFfbmxhJGxheW91dCRjbGlwW2d0XzFfbmxhJGxheW91dCRuYW1lID09ICJwYW5lbCJdIDwtICJvZmYiCmdnc2F2ZSgiLi9QbG90cy9sY2FfYWR2ZXJ0X3R5cGVfYWNjcmFfbm9sZWcudGlmZiIsIHBsb3QgPSBndF8xX25sYSwgc2NhbGUgPSAxLCBkcGkgPSAzMDApCmdnc2F2ZSgiLi9QbG90cyBsb3cgcmVzL2xjYV9hZHZlcnRfdHlwZV9hY2NyYV9ub2xlZy5qcGVnIiwgcGxvdCA9IGd0XzFfbmxhLCBkcGkgPSAzMDAsIHNjYWxlID0gMSkKCmBgYAoKIyMjRm9vZCBiZWluZyBzb2xkCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIFJlc2hhcGUgdGhlIHJlc3VsdHMgdGFibGUgaW50byBmb3JtYXQgZm9yIGdncGxvdApob2xkIDwtIHJlc3VsdHNbMTQ6MzksXSAjIFRha2Ugb25seSBvdXRsZXQgdmFyaWFibGVzCnRlbXAgPC0gbWVsdCgoaG9sZCksIG5hLnJtPVRSVUUpICMgVHVybiBpbnRvIGxvbmcgZm9ybWF0CgojIFBvbGFyIHBsb3QKYWNjcmFfbGNhMiA8LSBnZ3Bsb3QodGVtcCwgYWVzKHg9VmFsdWUsIHk9dmFsdWUsIGdyb3VwID0gdmFyaWFibGUsIGNvbG91cj12YXJpYWJsZSkpICsKICAgICAgICAgICAgICAgICAgZ2VvbV9saW5lKHNpemU9MS4yKSArIHlsaW0oMCwxKSArICAKICAgICAgICAgICAgICAgICAgY29vcmRfcG9sYXIoKSArIGxhYnMoeCA9IE5VTEwsIHkgPSBOVUxMLCBjb2xvciA9ICJMYXRlbnQgQ2xhc3MiKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCwgaGp1c3QgPSAxLjUsIHNpemUgPSAxMCkpICsKICAgICAgICAgICAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArIGdndGl0bGUoIkZvb2QgU29sZCIpICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDMiKSArIHRoZW1lKGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSkgKyB0aGVtZShwbG90Lm1hcmdpbj11bml0KGMoMC41LDIsMC41LDIpLCJjbSIpKSArIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gYygiZmF0c19vaWxzIiA9ICJmYXRzL29pbHMiLCAiZnJlc2hfZmlzaF9zaGVsbGZpc2giID0gImZyZXNoIGZpc2giLCAiY2FrZXNfc3dlZXRzIiA9ICJjYWtlcy9zd2VldHMiLCAiZnJlc2hfbWVhdF9wb3VsdHJ5IiA9ICJmcmVzaCBtZWF0IiwgImZyaWVkX3Jvb3RzX3R1YmVyc19wbG50bl9wb3RzIiA9ICJmcmllZCByb290IHZlZy4iLCAiZ3JhaW5fY2VyZWFsIiA9ICJncmFpbi9jZXJlYWwiLCAibGVndW1lc19wdWxzZXMiID0gImxlZ3VtZXMvcHVsc2VzIiwgIm1vZGVybl9taXhlZF9kaXNoZXMiID0gIm0uZGlzaCIsICJudXRzX3NlZWRzIj0gIm51dHMvc2VlZHMiLCAicHJvY3NzZF9mcmllZF9maXNoIiA9ICJwcm9jZXNzZWQgZmlzaCIsICJwcm9jc3NkX2ZyaWVkX21lYXRfcG91bHRyeSIgPSAicHJvY2Vzc2VkIG1lYXQiLCAic2F2b3VyeV9zbmFja3NfcGllcyIgPSAic2F2b3VyeSBzbmFja3MiLCAic29kYXNfc3dlZXRlbmVkX2JldnMiID0gInN3ZWV0ZW5lZCBkcmlua3MiLCAic291cHNfc3Rld3MiPSAic291cHMvc3Rld3MiLCAic3VnYXJfc3dlZXRfc3ByZWFkcyIgPSAic3dlZXRlbmVkIHNwcmVhZHMiLCAidGVhX2NvZmZlZSIgPSAidGVhL2NvZmZlZSIsICJ0cmFkX21peGVkX2Rpc2hlcyIgPSAidHJhZC4gZGlzaGVzIiwgInZlZ2V0YWJsZXMiID0gInZlZy4iLCAibm9uZnJpZWRfcm9vdHNfdHViZXJzX3BsbnRuX3BvdHMiID0gInJvb3QgdmVnLiIsICJmcmVzaF9qdWljZXMiID0gImZyZXNoIGp1aWNlcyIpKQphY2NyYV9sY2EyX25vbGVnIDwtIGFjY3JhX2xjYTIgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICMgUGxvdCB3aXRob3V0IGxlZ2VuZAoKIyBQbG90IGJ1dCBoYXZlIG5hbWVzIG92ZXJsYXAKZ3RfMiA8LSBnZ3Bsb3RfZ3RhYmxlKGdncGxvdF9idWlsZChhY2NyYV9sY2EyKSkgIyBXaXRoIGxlZ2VuZApndF8yJGxheW91dCRjbGlwW2d0XzIkbGF5b3V0JG5hbWUgPT0gInBhbmVsIl0gPC0gIm9mZiIKZ2dzYXZlKCIuL1Bsb3RzL2xjYV9mb29kX3NvbGRfYWNjcmEudGlmZiIsIHBsb3QgPSBndF8yLCBzY2FsZSA9IDEsIGRwaSA9IDMwMCkKZ2dzYXZlKCIuL1Bsb3RzIGxvdyByZXMvbGNhX2Zvb2Rfc29sZF9hY2NyYS5qcGVnIiwgcGxvdCA9IGd0XzIsIGRwaSA9IDMwMCwgc2NhbGUgPSAxKQpwbG90KGd0XzIpCgpndF8yX25sIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKGFjY3JhX2xjYTJfbm9sZWcpKSAjIFdpdGhvdXQgbGVnZW5kCmd0XzJfbmwkbGF5b3V0JGNsaXBbZ3RfMl9ubCRsYXlvdXQkbmFtZSA9PSAicGFuZWwiXSA8LSAib2ZmIgpnZ3NhdmUoIi4vUGxvdHMvbGNhX2Zvb2Rfc29sZF9hY2NyYV9ub2xlZy50aWZmIiwgcGxvdCA9IGd0XzJfbmwsIHNjYWxlID0gMSwgZHBpID0gMzAwKQpnZ3NhdmUoIi4vUGxvdHMgbG93IHJlcy9sY2FfZm9vZF9zb2xkX2FjY3JhX25vbGVnLmpwZWciLCBwbG90ID0gZ3RfMl9ubCwgZHBpID0gMzAwLCAgc2NhbGUgPSAxKQoKYGBgCgojIyNGb29kIGJlaW5nIGFkdmVydGlzZWQKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgUmVzaGFwZSB0aGUgcmVzdWx0cyB0YWJsZSBpbnRvIGZvcm1hdCBmb3IgZ2dwbG90CmhvbGQgPC0gcmVzdWx0c1s0MDo2MSxdICMgVGFrZSBvbmx5IG91dGxldCB2YXJpYWJsZXMKdGVtcCA8LSBtZWx0KChob2xkKSwgbmEucm09VFJVRSkgIyBUdXJuIGludG8gbG9uZyBmb3JtYXQKCiMgUG9sYXIgcGxvdAphY2NyYV9sY2EzIDwtIGdncGxvdCh0ZW1wLCBhZXMoeD1WYWx1ZSwgeT12YWx1ZSwgZ3JvdXAgPSB2YXJpYWJsZSwgY29sb3VyPXZhcmlhYmxlKSkgKwogICAgICAgICAgICAgICAgICBnZW9tX2xpbmUoc2l6ZT0xLjIpICsgeWxpbSgwLDEpICsgIAogICAgICAgICAgICAgICAgICBjb29yZF9wb2xhcigpICsgbGFicyh4ID0gTlVMTCwgeSA9IE5VTEwsIGNvbG9yID0gIkxhdGVudCBDbGFzcyIpICsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwLCBoanVzdCA9IDEuNSwgc2l6ZSA9IDEwKSkgKwogICAgICAgICAgICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpICsgZ2d0aXRsZSgiRm9vZCBBZHZlcnRpc2VkIikgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKyBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MyIpICsgdGhlbWUoYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpKSArIHRoZW1lKHBsb3QubWFyZ2luPXVuaXQoYygwLjUsMiwwLjUsMiksImNtIikpICsgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSBjKCJmYXRzX29pbHMiID0gImZhdHMvb2lscyIsICJmcmVzaF9maXNoX3NoZWxsZmlzaCIgPSAiZnJlc2ggZmlzaCIsICJjYWtlc19zd2VldHMiID0gImNha2VzL3N3ZWV0cyIsICJmcmVzaF9tZWF0X3BvdWx0cnkiID0gImZyZXNoIG1lYXQiLCAiZnJpZWRfcm9vdHNfdHViZXJzX3BsbnRuX3BvdHMiID0gImZyaWVkIHJvb3QgdmVnLiIsICJncmFpbl9jZXJlYWwiID0gImdyYWluL2NlcmVhbCIsICJsZWd1bWVzX3B1bHNlcyIgPSAibGVndW1lcyIsICJtb2Rlcm5fbWl4ZWRfZGlzaGVzIiA9ICJtLmRpc2giLCAibnV0c19zZWVkcyI9ICJudXRzL3NlZWRzIiwgInByb2Nzc2RfZnJpZWRfZmlzaCIgPSAicHJvY2Vzc2VkIGZpc2giLCAicHJvY3NzZF9mcmllZF9tZWF0X3BvdWx0cnkiID0gInByb2Nlc3NlZCBtZWF0IiwgInNhdm91cnlfc25hY2tzX3BpZXMiID0gInNhdm91cnkgc25hY2tzIiwgInNvZGFzX3N3ZWV0ZW5lZF9iZXZzIiA9ICJzd2VldGVuZWQgZHJpbmtzIiwgInNvdXBzX3N0ZXdzIj0gInNvdXBzL3N0ZXdzIiwgInN1Z2FyX3N3ZWV0X3NwcmVhZHMiID0gInN3ZWV0ZW5lZCBzcHJlYWRzIiwgInRlYV9jb2ZmZWUiID0gInRlYS9jb2ZmZWUiLCAidHJhZF9taXhlZF9kaXNoZXMiID0gInRyYWQuIGRpc2hlcyIsICJ2ZWdldGFibGVzIiA9ICJ2ZWcuIikpCmFjY3JhX2xjYTNfbm9sZWcgPC0gYWNjcmFfbGNhMyArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgIyBQbG90IHdpdGhvdXQgbGVnZW5kCgojIFBsb3QgYnV0IGhhdmUgbmFtZXMgb3ZlcmxhcApndF8zIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKGFjY3JhX2xjYTMpKSAjIFdpdGggbGVnZW5kCmd0XzMkbGF5b3V0JGNsaXBbZ3RfMyRsYXlvdXQkbmFtZSA9PSAicGFuZWwiXSA8LSAib2ZmIgpnZ3NhdmUoIi4vUGxvdHMvbGNhX2Zvb2RfYWR2X2FjY3JhLnRpZmYiLCBwbG90ID0gZ3RfMywgc2NhbGUgPSAxLCBkcGkgPSAzMDApCmdnc2F2ZSgiLi9QbG90cyBsb3cgcmVzL2xjYV9mb29kX2Fkdl9hY2NyYS5qcGVnIiwgcGxvdCA9IGd0XzMsIGRwaSA9IDMwMCwgc2NhbGUgPSAxKQpwbG90KGd0XzMpCgpndF8zX25sIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKGFjY3JhX2xjYTNfbm9sZWcpKSAjIFdpdGhvdXQgbGVnZW5kCmd0XzNfbmwkbGF5b3V0JGNsaXBbZ3RfM19ubCRsYXlvdXQkbmFtZSA9PSAicGFuZWwiXSA8LSAib2ZmIgpnZ3NhdmUoIi4vUGxvdHMgbG93IHJlcy9sY2FfZm9vZF9hZHZfYWNjcmFfbm9sZWcuanBlZyIsIHBsb3QgPSBndF8zX25sLCBkcGkgPSAzMDAsIHNjYWxlID0gMSkKCmBgYAoKTGV0J3Mgam9pbiB0aGVtIHRvZ2V0aGVyIGludG8gYSBzaW5nbGUgcGxvdC4KCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoZ3JpZEV4dHJhKQojIENyZWF0ZSBibGFuayBwbG90IHRvIGNlbnRyZSBsZWdlbmQKYmxhbmtQbG90IDwtIGdncGxvdCgpK2dlb21fYmxhbmsoYWVzKDEsMSkpICsgCiAgY293cGxvdDo6dGhlbWVfbm90aGluZygpCgojIEpvaW4gdG9nZXRoZXIgcGxvdHMgaW50byBzaW5nbGUgcGxvdAojIFNhdmUgYXMgUERGCnBkZigiLi9QbG90cy9hY2NyYV9hbGxfcGxvdHMucGRmIiwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gMTApIApncmlkLmFycmFuZ2UoZ3RfMV9ubCwgZ3RfMV9ubGEsIGd0XzJfbmwsIGd0XzNfbmwsIGxlZ2VuZCwgbmNvbCA9IDIsIG5yb3cgPSAzLAogICAgICAgICAgICAgICAgICAgICAgd2lkdGhzID0gYygxMCwgMTApLCBoZWlnaHRzID0gYygxMCwgMTAsIDQpKQpkZXYub2ZmKCkKCiMgU2F2ZSBhcyBpbWFnZS90aWZmIGZpbGUKdGlmZigiLi9QbG90cy9hY2NyYV9hbGxfcGxvdHMudGlmZiIsIHdpZHRoID0gMTAsIGhlaWdodCA9IDEwLCB1bml0cyA9ICJpbiIsIHJlcyA9IDMwMCkKZ3JpZC5hcnJhbmdlKGd0XzFfbmwsIGd0XzFfbmxhLCBndF8yX25sLCBndF8zX25sLCBsZWdlbmQsIG5jb2wgPSAyLCBucm93ID0gMywKICAgICAgICAgICAgICAgICAgICAgIHdpZHRocyA9IGMoMTAsIDEwKSwgaGVpZ2h0cyA9IGMoMTAsIDEwLCA0KSkKZGV2Lm9mZigpCgpgYGAKCiNIbwoKTGFzdCBzaXRlIGlzIEhvLiBGaXJzdCwgd2UgYXNzZXNzIGhvdyBtYW55IGxhdGVudCBjbGFzc2VzLgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBTdWJzZXQgQWNjcmEgZGF0YSBvbmx5CmhvIDwtIGdoYW5hW2doYW5hJGxvY2F0aW9uID09ICJIbyJdCgojIERlZmluZSB2YXJpYWJsZXMgdG8gYmUgdXNlZCBpbiBMQ0EgdG8gZXN0aW1hdGUgZ3JvdXBzICh0b28gbWFueSB2YXJpYWJsZXM/KQpmIDwtIHdpdGgoaG8sIAogICAgICAgICAgY2JpbmQoIyBUeXBlIG9mIG91dGxldAogICAgICAgICAgIG91dGxldF93X2FkdmVydCwgb3V0bGV0X25vX2FkdmVydCwgYWR2ZXJ0X29ubHksIHN1cGVybWFya2V0LCBzaG9wLCBraW9zaywgc3RhbmRfdGFibGVfdG9wLCBsb2NhbF92ZW5kb3IsIHJlc3RhdXJhbnQsIGJhcl9wdWIsIG90aGVyX291dGxldCwgYmlsbGJvYXJkX2FkdiwgcG9zdGVyX2Fkdiwgb25zaXRlX2FkdiwgcGFpbnRpbmdfYWR2LAogICAgICAgICAgICMgRm9vZHMgc29sZAogICAgICAgICAgIGdyYWluX2NlcmVhbCwgZnJlc2hfbWVhdF9wb3VsdHJ5LCBmcmVzaF9maXNoX3NoZWxsZmlzaCwgcHJvY3NzZF9mcmllZF9tZWF0X3BvdWx0cnksIHByb2Nzc2RfZnJpZWRfZmlzaCwgdHJhZF9taXhlZF9kaXNoZXMsIG1vZGVybl9taXhlZF9kaXNoZXMsIHNvdXBzX3N0ZXdzLCBmcmllZF9yb290c190dWJlcnNfcGxudG5fcG90cywgbm9uZnJpZWRfcm9vdHNfdHViZXJzX3BsbnRuX3BvdHMsIGZydWl0cywgdmVnZXRhYmxlcywgY2FrZXNfc3dlZXRzLCBzYXZvdXJ5X3NuYWNrc19waWVzLCBzb2Rhc19zd2VldGVuZWRfYmV2cywgbWlsaywgZnJlc2hfanVpY2VzLCBhbGNvaG9sLCBzdWdhcl9zd2VldF9zcHJlYWRzLCB0ZWFfY29mZmVlLCBmYXRzX29pbHMsIG51dHNfc2VlZHMsIGxlZ3VtZXNfcHVsc2VzLCBjb25kaW1lbnRzLCBlZ2dzLCBvdGhlciwKICAgICAgICAgICAjIEFkdmVydGlzZW1lbnRzCiAgICAgICAgICAgYWR2X2dyYWluX2NlcmVhbCwgYWR2X2ZyZXNoX21lYXRfcG91bHRyeSwgYWR2X2ZyZXNoX2Zpc2hfc2hlbGxmaXNoLCBhZHZfcHJvY3NzZF9mcmllZF9tZWF0X3BvdWx0cnksIGFkdl9wcm9jc3NkX2ZyaWVkX2Zpc2gsIGFkdl90cmFkX21peGVkX2Rpc2hlcywgYWR2X21vZGVybl9taXhlZF9kaXNoZXMsIGFkdl9zb3Vwc19zdGV3cywgYWR2X2ZyaWVkX3Jvb3RzX3R1YmVyc19wbG50bl9wb3RzLCBhZHZfbm9uZnJpZWRfcm9vdHNfdHViZXJzX3BsbnRuX3BvdHMsIGFkdl9mcnVpdHMsIGFkdl92ZWdldGFibGVzLCBhZHZfY2FrZXNfc3dlZXRzLCBhZHZfc2F2b3VyeV9zbmFja3NfcGllcywgYWR2X3NvZGFzX3N3ZWV0ZW5lZF9iZXZzLCBhZHZfbWlsaywgYWR2X2ZyZXNoX2p1aWNlcywgYWR2X2FsY29ob2wsIGFkdl9zdWdhcl9zd2VldF9zcHJlYWRzLCBhZHZfdGVhX2NvZmZlZSwgYWR2X2ZhdHNfb2lscywgYWR2X251dHNfc2VlZHMsIGFkdl9sZWd1bWVzX3B1bHNlcywgYWR2X2NvbmRpbWVudHMsIGFkdl9lZ2dzLCBhZHZfb3RoZXIpfjEpCgojIElkZW50aWZ5IGJlc3QgbnVtYmVyIG9mIGdyb3VwcwoKbnVtYmVycyA8LSBjKDE6MTApCgpmb3IgKGkgaW4gbnVtYmVycykgewogIHRlbXAgPC0gcG9MQ0EoZiwgaG8sIG5jbGFzcz1pLCBucmVwPTIwLCBtYXhpdGVyPTEwMDAwMCwgdmVyYm9zZT1GQUxTRSwgbmEucm09VCkKICBhc3NpZ24ocGFzdGUwKCJsY2FfYWxsIixpKSwgdGVtcCkKICBybSh0ZW1wKQp9CgojIENvbXBhcmUgc29sdXRpb25zCkFJQyA8LSBjKHJiaW5kKGxjYV9hbGwxJGFpYywgbGNhX2FsbDIkYWljLCBsY2FfYWxsMyRhaWMsIGxjYV9hbGw0JGFpYywgbGNhX2FsbDUkYWljLAogICAgICAgICAgICAgICBsY2FfYWxsNiRhaWMsIGxjYV9hbGw3JGFpYywgbGNhX2FsbDgkYWljLCBsY2FfYWxsOSRhaWMsIGxjYV9hbGwxMCRhaWMpKQpCSUMgPC0gYyhyYmluZChsY2FfYWxsMSRiaWMsIGxjYV9hbGwyJGJpYywgbGNhX2FsbDMkYmljLCBsY2FfYWxsNCRiaWMsIGxjYV9hbGw1JGJpYywKICAgICAgICAgICAgICAgbGNhX2FsbDYkYmljLCBsY2FfYWxsNyRiaWMsIGxjYV9hbGw4JGJpYywgbGNhX2FsbDkkYmljLCBsY2FfYWxsMTAkYmljKSkKR3NxIDwtIGMocmJpbmQobGNhX2FsbDEkR3NxLCBsY2FfYWxsMiRHc3EsIGxjYV9hbGwzJEdzcSwgbGNhX2FsbDQkR3NxLCBsY2FfYWxsNSRHc3EsCiAgICAgICAgICAgICAgIGxjYV9hbGw2JEdzcSwgbGNhX2FsbDckR3NxLCBsY2FfYWxsOCRHc3EsIGxjYV9hbGw5JEdzcSwgbGNhX2FsbDEwJEdzcSkpCkNoaXNxIDwtIGMocmJpbmQobGNhX2FsbDEkQ2hpc3EsIGxjYV9hbGwyJENoaXNxLCBsY2FfYWxsMyRDaGlzcSwgbGNhX2FsbDQkQ2hpc3EsIGxjYV9hbGw1JENoaXNxLAogICAgICAgICAgICAgICAgIGxjYV9hbGw2JENoaXNxLCBsY2FfYWxsNyRDaGlzcSwgbGNhX2FsbDgkQ2hpc3EsIGxjYV9hbGw5JENoaXNxLCBsY2FfYWxsMTAkQ2hpc3EpKQpHcm91cHMgPC0gYygxOjEwKQpudW1iX2dycHNfYWxsIDwtIGNiaW5kKEdyb3VwcyxBSUMsQklDLEdzcSxDaGlzcSkgIyBQdXQgdG9nZXRoZXIgaW4gb25lIHRhYmxlCndyaXRlLnRhYmxlKG51bWJfZ3Jwc19hbGwsICIuL251bWJlcl9vZl9ncm91cHNfaG8udHh0Iiwgc2VwID0gIlx0Iiwgcm93Lm5hbWVzID0gRkFMU0UpICMgU2F2ZQoKIyBQbG90IHZhbHVlcwpudW1iX2dycHNfYWxsIDwtIGFzLmRhdGEuZnJhbWUobnVtYl9ncnBzX2FsbCkKcGxvdDEgPC0gZ2dwbG90KG51bWJfZ3Jwc19hbGwsIGFlcyh4ID0gR3JvdXBzLCB5ID0gQUlDKSkgKyBnZW9tX3BvaW50KCkgKyB4bGFiKCJOdW1iZXIgb2YgY2xhc3NlcyIpICsgeWxhYigiQWthaWtlIEluZm9ybWF0aW9uIENyaXRlcmlvbiIpICsgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKDAsIDEwKSwgYnJlYWtzID0gc2VxKDAsMTAsMikpCmdnc2F2ZSgiLi9QbG90cy9ob19sY2FfYWljLnRpZmYiLCBwbG90ID0gcGxvdDEsIGRwaSA9IDMwMCwgd2lkdGggPSA3LCBoZWlnaHQgPSA3KQpnZ3NhdmUoIi4vUGxvdHMgbG93IHJlcy9ob19sY2FfYWljLmpwZWciLCBwbG90ID0gcGxvdDEsIGRwaSA9IDMwMCwgd2lkdGggPSA3LCBoZWlnaHQgPSA3KQpwbG90MQoKcGxvdDIgPC0gZ2dwbG90KG51bWJfZ3Jwc19hbGwsIGFlcyh4ID0gR3JvdXBzLCB5ID0gQklDKSkgKyBnZW9tX3BvaW50KCkgKyB4bGFiKCJOdW1iZXIgb2YgY2xhc3NlcyIpICsgeWxhYigiQmF5ZXNpYW4gSW5mb3JtYXRpb24gQ3JpdGVyaW9uIikgKyBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMCwgMTApLCBicmVha3MgPSBzZXEoMCwxMCwyKSkKZ2dzYXZlKCIuL1Bsb3RzL2hvX2xjYV9iaWMudGlmZiIsIHBsb3QgPSBwbG90MiwgZHBpID0gMzAwLCB3aWR0aCA9IDcsIGhlaWdodCA9IDcpCmdnc2F2ZSgiLi9QbG90cyBsb3cgcmVzL2hvX2xjYV9iaWMuanBlZyIsIHBsb3QgPSBwbG90MiwgZHBpID0gMzAwLCB3aWR0aCA9IDcsIGhlaWdodCA9IDcpCnBsb3QyCgpwbG90MyA8LSBnZ3Bsb3QobnVtYl9ncnBzX2FsbCwgYWVzKHggPSBHcm91cHMsIHkgPSBHc3EpKSArIGdlb21fcG9pbnQoKSArIHhsYWIoIk51bWJlciBvZiBjbGFzc2VzIikgKyB5bGFiKCJHLXNxdWFyZWQgc3RhdGlzdGljIikgKyBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMCwgMTApLCBicmVha3MgPSBzZXEoMCwxMCwyKSkKZ2dzYXZlKCIuL1Bsb3RzL2hvX2xjYV9nc3EudGlmZiIsIHBsb3QgPSBwbG90MywgZHBpID0gMzAwLCB3aWR0aCA9IDcsIGhlaWdodCA9IDcpCmdnc2F2ZSgiLi9QbG90cyBsb3cgcmVzL2hvX2xjYV9nc3EuanBlZyIsIHBsb3QgPSBwbG90MywgZHBpID0gMzAwLCB3aWR0aCA9IDcsIGhlaWdodCA9IDcpCnBsb3QzCgpwbG90NCA8LSBnZ3Bsb3QobnVtYl9ncnBzX2FsbCwgYWVzKHggPSBHcm91cHMsIHkgPSBDaGlzcSkpICsgZ2VvbV9wb2ludCgpICsgeGxhYigiTnVtYmVyIG9mIGNsYXNzZXMiKSArIHlsYWIoIkNoaS1zcXVhcmVkIHN0YXRpc3RpYyIpICsgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKDAsIDEwKSwgYnJlYWtzID0gc2VxKDAsMTAsMikpCmdnc2F2ZSgiLi9QbG90cy9ob19sY2FfY2hpc3EudGlmZiIsIHBsb3QgPSBwbG90NCwgZHBpID0gMzAwLCB3aWR0aCA9IDcsIGhlaWdodCA9IDcpCmdnc2F2ZSgiLi9QbG90cyBsb3cgcmVzL2hvX2xjYV9jaGlzcS5qcGVnIiwgcGxvdCA9IHBsb3Q0LCBkcGkgPSAzMDAsIHdpZHRoID0gNywgaGVpZ2h0ID0gNykKcGxvdDQKCmBgYAoKSG1tbSwgYSA2IGdyb3VwIHNvbHV0aW9uIHNlZW1zIGJlc3QgaGVyZSAtIHJvdWdobHkgd2hlcmUgaXQgbGV2ZWxzIG9mZiBvbiB0aHJlZSBvZiB0aGUgbWV0cmljcy4gVGhlIGZpbmFsIG9uZSBkb2Vzbid0IHJlYWxseSBoZWxwIHVzIGF0IGFsbC4gTGV0J3MgaGF2ZSBhIGxvb2sgYXQgdGhlIGNsdXN0ZXIgY2VudHJlcyBhbmQgc3RhcnQgaW50ZXJwcmV0aW5nIHRoZSBjbHVzdGVycy4KCmBgYHtyfQpzb3VyY2UoIi4vdGlkeV9wb0xDQV9yZXN1bHRzX2hvLlIiKSAjIEZvciA2IGNsYXNzIHNvbHV0aW9uLCBpZiBjaGFuZ2UgbnVtYmVyIG9mIGNsYXNzZXMgdGhlbiBuZWVkIHRvIG1hbnVhbGx5IGVkaXQKd3JpdGUuY3N2KHJlc3VsdHMsICIuL2NvbmRfcHJvYl9oby5jc3YiKSAjIFNhdmUKcmVzdWx0cwpgYGAKCldlIHdpbGwgaW50ZXJwcmV0IGVhY2ggbGF0ZW50IGNsYXNzIGxpa2UgYmVmb3JlIC0gYnkgdmFyaWFibGUgdHlwZS4KCiMjI091dGxldCBUeXBlCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ3JpZCkKCiMgUmVzaGFwZSB0aGUgcmVzdWx0cyB0YWJsZSBpbnRvIGZvcm1hdCBmb3IgZ2dwbG90CmxpYnJhcnkocmVzaGFwZTIpCmhvbGQgPC0gcmVzdWx0c1s0OjExLF0gIyBUYWtlIG9ubHkgb3V0bGV0IHZhcmlhYmxlcwp0ZW1wIDwtIG1lbHQoKGhvbGQpLCBuYS5ybT1UUlVFKSAjIFR1cm4gaW50byBsb25nIGZvcm1hdAoKIyBQb2xhciBwbG90CmhvX2xjYTEgPC0gZ2dwbG90KHRlbXAsIGFlcyh4PVZhbHVlLCB5PXZhbHVlLCBncm91cCA9IHZhcmlhYmxlLCBjb2xvdXI9dmFyaWFibGUpKSArCiAgICAgICAgICAgICAgICAgIGdlb21fbGluZShzaXplPTEuMikgKyB5bGltKDAsMSkgKyAgCiAgICAgICAgICAgICAgICAgIGNvb3JkX3BvbGFyKCkgKyBsYWJzKHggPSBOVUxMLCB5ID0gTlVMTCwgY29sb3IgPSAiTGF0ZW50IENsYXNzIikgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsIGhqdXN0ID0gMS41LCBzaXplID0gMTApKSArCiAgICAgICAgICAgICAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikgKyBnZ3RpdGxlKCJPdXRsZXQgVHlwZXMiKSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQzIikgKyB0aGVtZShheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MueT1lbGVtZW50X2JsYW5rKCkpICsgdGhlbWUocGxvdC5tYXJnaW49dW5pdChjKDAuNSwyLDAuNSwyKSwiY20iKSkgKyBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGMoImJhcl9wdWIiID0gImJhci9wdWIiLCAiYmlsbGJvYXJkX2FkdiIgPSAiYmlsbGJvYXJkIGFkdi4iLCAibG9jYWxfdmVuZG9yIiA9ICJsb2NhbCB2ZW5kb3IiLCAib25zaXRlX2FkdiIgPSAib25zaXRlIGFkdi4iLCAic3RhbmRfdGFibGVfdG9wIiA9ICJ0YWJsZXRvcCIsICJwb3N0ZXJfYWR2IiA9ICJwb3N0ZXIgYWR2LiIsICJvdGhlcl9hZHYiID0gIm90aGVyIGFkdi4iLCAib3V0bGV0X25vX2FkdmVydCIgPSAib3V0bGV0IG5vIGFkdi4iLCAib3V0bGV0X3dfYWR2ZXJ0Ij0gIm91dGxldCB3aXRoIGFkdi4iLCAicGFpbnRpbmdfYWR2IiA9ICJwYWludGluZyBhZHYuIiwgInBvc3Rlcl9hZHYiID0gInBvc3RlciBhZHYuIiwgImFkdmVydF9vbmx5IiA9ICJhZHZlcnQiLCAib3RoZXJfb3V0bGV0IiA9ICJvdGhlciBvdXRsZXQiLCAic29jX21hcmt0X2FkdiIgPSAic29jaWFsIG1lZGlhIGFkdi4iKSkKaG9fbGNhMV9ub2xlZyA8LSBob19sY2ExICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSAjIFBsb3Qgd2l0aG91dCBsZWdlbmQKCiMgUGxvdCBidXQgaGF2ZSBuYW1lcyBvdmVybGFwCmd0XzEgPC0gZ2dwbG90X2d0YWJsZShnZ3Bsb3RfYnVpbGQoaG9fbGNhMSkpICMgV2l0aCBsZWdlbmQKZ3RfMSRsYXlvdXQkY2xpcFtndF8xJGxheW91dCRuYW1lID09ICJwYW5lbCJdIDwtICJvZmYiCmdnc2F2ZSgiLi9QbG90cy9sY2Ffb3V0bGV0X3R5cGVfaG8udGlmZiIsIHBsb3QgPSBndF8xLCBzY2FsZSA9IDEsIGRwaSA9IDMwMCkKZ2dzYXZlKCIuL1Bsb3RzIGxvdyByZXMvbGNhX291dGxldF90eXBlX2hvLmpwZWciLCBwbG90ID0gZ3RfMSwgZHBpID0gMzAwLCBzY2FsZSA9IDEpCnBsb3QoZ3RfMSkKCmd0XzFfbmwgPC0gZ2dwbG90X2d0YWJsZShnZ3Bsb3RfYnVpbGQoaG9fbGNhMV9ub2xlZykpICMgV2l0aG91dCBsZWdlbmQKZ3RfMV9ubCRsYXlvdXQkY2xpcFtndF8xX25sJGxheW91dCRuYW1lID09ICJwYW5lbCJdIDwtICJvZmYiCmdnc2F2ZSgiLi9QbG90cy9sY2Ffb3V0bGV0X3R5cGVfaG9fbm9sZWcudGlmZiIsIHBsb3QgPSBndF8xX25sLCBzY2FsZSA9IDEsIGRwaSA9IDMwMCkKZ2dzYXZlKCIuL1Bsb3RzIGxvdyByZXMvbGNhX291dGxldF90eXBlX2hvX25vbGVnLmpwZWciLCBwbG90ID0gZ3RfMV9ubCwgZHBpID0gMzAwLCBzY2FsZSA9IDEpCgojIEZ1bmN0aW9uIHRvIHN0b3JlIGxlZ2VuZApnZXRfbGVnZW5kPC1mdW5jdGlvbihteWdncGxvdCl7CiAgdG1wIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKG15Z2dwbG90KSkKICBsZWcgPC0gd2hpY2goc2FwcGx5KHRtcCRncm9icywgZnVuY3Rpb24oeCkgeCRuYW1lKSA9PSAiZ3VpZGUtYm94IikKICBsZWdlbmQgPC0gdG1wJGdyb2JzW1tsZWddXQogIHJldHVybihsZWdlbmQpCn0KCmxlZ2VuZCA8LSBnZXRfbGVnZW5kKGhvX2xjYTEpICMgU3RvcmUgbGVnZW5kCgpgYGAKCiMjIyBBZHZlcnQgVHlwZQoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdyaWQpCgojIFJlc2hhcGUgdGhlIHJlc3VsdHMgdGFibGUgaW50byBmb3JtYXQgZm9yIGdncGxvdApsaWJyYXJ5KHJlc2hhcGUyKQpob2xkIDwtIHJlc3VsdHNbYygxOjMsIDEyOjE1KSxdICMgVGFrZSBvbmx5IG91dGxldCB2YXJpYWJsZXMKdGVtcCA8LSBtZWx0KChob2xkKSwgbmEucm09VFJVRSkgIyBUdXJuIGludG8gbG9uZyBmb3JtYXQKCiMgUG9sYXIgcGxvdApob19sY2EyYSA8LSBnZ3Bsb3QodGVtcCwgYWVzKHg9VmFsdWUsIHk9dmFsdWUsIGdyb3VwID0gdmFyaWFibGUsIGNvbG91cj12YXJpYWJsZSkpICsKICAgICAgICAgICAgICAgICAgZ2VvbV9saW5lKHNpemU9MS4yKSArIHlsaW0oMCwxKSArICAKICAgICAgICAgICAgICAgICAgY29vcmRfcG9sYXIoKSArIGxhYnMoeCA9IE5VTEwsIHkgPSBOVUxMLCBjb2xvciA9ICJMYXRlbnQgQ2xhc3MiKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCwgaGp1c3QgPSAxLjUsIHNpemUgPSAxMCkpICsKICAgICAgICAgICAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArIGdndGl0bGUoIkFkdmVydCBUeXBlcyIpICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDMiKSArIHRoZW1lKGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSkgKyB0aGVtZShwbG90Lm1hcmdpbj11bml0KGMoMC41LDIsMC41LDIpLCJjbSIpKSArIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gYygiYmlsbGJvYXJkX2FkdiIgPSAiYmlsbGJvYXJkIGFkdmVydCIsICJvbnNpdGVfYWR2IiA9ICJvbnNpdGUgYWR2ZXJ0IiwgInBvc3Rlcl9hZHYiID0gInBvc3RlciBhZHZlcnQiLCAib3V0bGV0X25vX2FkdmVydCIgPSAib3V0bGV0IG5vIGFkdmVydCIsICJvdXRsZXRfd19hZHZlcnQiPSAib3V0bGV0IHdpdGggYWR2ZXJ0IiwgInBhaW50aW5nX2FkdiIgPSAicGFpbnRpbmciLCAiYWR2ZXJ0X29ubHkiID0gImFkdmVydCIpKQpob19sY2EyYV9ub2xlZ2EgPC0gaG9fbGNhMmEgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICMgUGxvdCB3aXRob3V0IGxlZ2VuZAoKIyBQbG90IGJ1dCBoYXZlIG5hbWVzIG92ZXJsYXAKZ3RfMWEgPC0gZ2dwbG90X2d0YWJsZShnZ3Bsb3RfYnVpbGQoaG9fbGNhMmEpKSAjIFdpdGggbGVnZW5kCmd0XzFhJGxheW91dCRjbGlwW2d0XzFhJGxheW91dCRuYW1lID09ICJwYW5lbCJdIDwtICJvZmYiCmdnc2F2ZSgiLi9QbG90cy9sY2FfYWR2ZXJ0X3R5cGVfaG8udGlmZiIsIHBsb3QgPSBndF8xYSwgc2NhbGUgPSAxLCBkcGkgPSAzMDApCmdnc2F2ZSgiLi9QbG90cyBsb3cgcmVzL2xjYV9hZHZlcnRfdHlwZV9oby5qcGVnIiwgcGxvdCA9IGd0XzFhLCBkcGkgPSAzMDAsICBzY2FsZSA9IDEpCnBsb3QoZ3RfMWEpCgpndF8xX25sYSA8LSBnZ3Bsb3RfZ3RhYmxlKGdncGxvdF9idWlsZChob19sY2EyYV9ub2xlZ2EpKSAjIFdpdGhvdXQgbGVnZW5kCmd0XzFfbmxhJGxheW91dCRjbGlwW2d0XzFfbmxhJGxheW91dCRuYW1lID09ICJwYW5lbCJdIDwtICJvZmYiCmdnc2F2ZSgiLi9QbG90cy9sY2FfYWR2ZXJ0X3R5cGVfaG9fbm9sZWcudGlmZiIsIHBsb3QgPSBndF8xX25sYSwgc2NhbGUgPSAxLCBkcGkgPSAzMDApCmdnc2F2ZSgiLi9QbG90cyBsb3cgcmVzL2xjYV9hZHZlcnRfdHlwZV9ob19ub2xlZy5qcGVnIiwgcGxvdCA9IGd0XzFfbmxhLCBkcGkgPSAzMDAsIHNjYWxlID0gMSkKCmBgYAoKIyMjRm9vZCBiZWluZyBzb2xkCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIFJlc2hhcGUgdGhlIHJlc3VsdHMgdGFibGUgaW50byBmb3JtYXQgZm9yIGdncGxvdApob2xkIDwtIHJlc3VsdHNbMTY6NDEsXSAjIFRha2Ugb25seSBvdXRsZXQgdmFyaWFibGVzCnRlbXAgPC0gbWVsdCgoaG9sZCksIG5hLnJtPVRSVUUpICMgVHVybiBpbnRvIGxvbmcgZm9ybWF0CgojIFBvbGFyIHBsb3QKaG9fbGNhMiA8LSBnZ3Bsb3QodGVtcCwgYWVzKHg9VmFsdWUsIHk9dmFsdWUsIGdyb3VwID0gdmFyaWFibGUsIGNvbG91cj12YXJpYWJsZSkpICsKICAgICAgICAgICAgICAgICAgZ2VvbV9saW5lKHNpemU9MS4yKSArIHlsaW0oMCwxKSArICAKICAgICAgICAgICAgICAgICAgY29vcmRfcG9sYXIoKSArIGxhYnMoeCA9IE5VTEwsIHkgPSBOVUxMLCBjb2xvciA9ICJMYXRlbnQgQ2xhc3MiKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCwgaGp1c3QgPSAxLjUsIHNpemUgPSAxMCkpICsKICAgICAgICAgICAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArIGdndGl0bGUoIkZvb2QgU29sZCIpICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDMiKSArIHRoZW1lKGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSkgKyB0aGVtZShwbG90Lm1hcmdpbj11bml0KGMoMC41LDIsMC41LDIpLCJjbSIpKSArIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gYygiZmF0c19vaWxzIiA9ICJmYXRzL29pbHMiLCAiZnJlc2hfZmlzaF9zaGVsbGZpc2giID0gImZyZXNoIGZpc2giLCAiY2FrZXNfc3dlZXRzIiA9ICJjYWtlcy9zd2VldHMiLCAiZnJlc2hfbWVhdF9wb3VsdHJ5IiA9ICJmcmVzaCBtZWF0IiwgImZyaWVkX3Jvb3RzX3R1YmVyc19wbG50bl9wb3RzIiA9ICJmcmllZCByb290IHZlZy4iLCAiZ3JhaW5fY2VyZWFsIiA9ICJncmFpbi9jZXJlYWwiLCAibGVndW1lc19wdWxzZXMiID0gImxlZ3VtZXMvcHVsc2VzIiwgIm1vZGVybl9taXhlZF9kaXNoZXMiID0gIm0uZGlzaCIsICJudXRzX3NlZWRzIj0gIm51dHMvc2VlZHMiLCAicHJvY3NzZF9mcmllZF9maXNoIiA9ICJwcm9jZXNzZWQgZmlzaCIsICJwcm9jc3NkX2ZyaWVkX21lYXRfcG91bHRyeSIgPSAicHJvY2Vzc2VkIG1lYXQiLCAic2F2b3VyeV9zbmFja3NfcGllcyIgPSAic2F2b3VyeSBzbmFja3MiLCAic29kYXNfc3dlZXRlbmVkX2JldnMiID0gInN3ZWV0ZW5lZCBkcmlua3MiLCAic291cHNfc3Rld3MiPSAic291cHMvc3Rld3MiLCAic3VnYXJfc3dlZXRfc3ByZWFkcyIgPSAic3dlZXRlbmVkIHNwcmVhZHMiLCAidGVhX2NvZmZlZSIgPSAidGVhL2NvZmZlZSIsICJ0cmFkX21peGVkX2Rpc2hlcyIgPSAidHJhZC4gZGlzaGVzIiwgInZlZ2V0YWJsZXMiID0gInZlZy4iLCAibm9uZnJpZWRfcm9vdHNfdHViZXJzX3BsbnRuX3BvdHMiID0gInJvb3QgdmVnLiIsICJmcmVzaF9qdWljZXMiID0gImZyZXNoIGp1aWNlcyIpKQpob19sY2EyX25vbGVnIDwtIGhvX2xjYTIgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICMgUGxvdCB3aXRob3V0IGxlZ2VuZAoKIyBQbG90IGJ1dCBoYXZlIG5hbWVzIG92ZXJsYXAKZ3RfMiA8LSBnZ3Bsb3RfZ3RhYmxlKGdncGxvdF9idWlsZChob19sY2EyKSkgIyBXaXRoIGxlZ2VuZApndF8yJGxheW91dCRjbGlwW2d0XzIkbGF5b3V0JG5hbWUgPT0gInBhbmVsIl0gPC0gIm9mZiIKZ2dzYXZlKCIuL1Bsb3RzL2xjYV9mb29kX3NvbGRfaG8udGlmZiIsIHBsb3QgPSBndF8yLCBzY2FsZSA9IDEsIGRwaSA9IDMwMCkKZ2dzYXZlKCIuL1Bsb3RzIGxvdyByZXMvbGNhX2Zvb2Rfc29sZF9oby5qcGVnIiwgcGxvdCA9IGd0XzIsIGRwaSA9IDMwMCwgc2NhbGUgPSAxKQpwbG90KGd0XzIpCgpndF8yX25sIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKGhvX2xjYTJfbm9sZWcpKSAjIFdpdGhvdXQgbGVnZW5kCmd0XzJfbmwkbGF5b3V0JGNsaXBbZ3RfMl9ubCRsYXlvdXQkbmFtZSA9PSAicGFuZWwiXSA8LSAib2ZmIgpnZ3NhdmUoIi4vUGxvdHMvbGNhX2Zvb2Rfc29sZF9ob19ub2xlZy50aWZmIiwgcGxvdCA9IGd0XzJfbmwsIHNjYWxlID0gMSwgZHBpID0gMzAwKQpnZ3NhdmUoIi4vUGxvdHMgbG93IHJlcy9sY2FfZm9vZF9zb2xkX2hvX25vbGVnLmpwZWciLCBwbG90ID0gZ3RfMl9ubCwgZHBpID0gMzAwLCBzY2FsZSA9IDEpCgpgYGAKCiMjI0Zvb2QgYmVpbmcgYWR2ZXJ0aXNlZAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBSZXNoYXBlIHRoZSByZXN1bHRzIHRhYmxlIGludG8gZm9ybWF0IGZvciBnZ3Bsb3QKaG9sZCA8LSByZXN1bHRzWzQyOjY2LF0gIyBUYWtlIG9ubHkgb3V0bGV0IHZhcmlhYmxlcwp0ZW1wIDwtIG1lbHQoKGhvbGQpLCBuYS5ybT1UUlVFKSAjIFR1cm4gaW50byBsb25nIGZvcm1hdAoKIyBQb2xhciBwbG90CmhvX2xjYTMgPC0gZ2dwbG90KHRlbXAsIGFlcyh4PVZhbHVlLCB5PXZhbHVlLCBncm91cCA9IHZhcmlhYmxlLCBjb2xvdXI9dmFyaWFibGUpKSArCiAgICAgICAgICAgICAgICAgIGdlb21fbGluZShzaXplPTEuMikgKyB5bGltKDAsMSkgKyAgCiAgICAgICAgICAgICAgICAgIGNvb3JkX3BvbGFyKCkgKyBsYWJzKHggPSBOVUxMLCB5ID0gTlVMTCwgY29sb3IgPSAiTGF0ZW50IENsYXNzIikgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsIGhqdXN0ID0gMS41LCBzaXplID0gMTApKSArCiAgICAgICAgICAgICAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikgKyBnZ3RpdGxlKCJGb29kIEFkdmVydGlzZWQiKSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQzIikgKyB0aGVtZShheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MueT1lbGVtZW50X2JsYW5rKCkpICsgdGhlbWUocGxvdC5tYXJnaW49dW5pdChjKDAuNSwyLDAuNSwyKSwiY20iKSkgKyBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGMoImZhdHNfb2lscyIgPSAiZmF0cy9vaWxzIiwgImZyZXNoX2Zpc2hfc2hlbGxmaXNoIiA9ICJmcmVzaCBmaXNoIiwgImNha2VzX3N3ZWV0cyIgPSAiY2FrZXMvc3dlZXRzIiwgImZyZXNoX21lYXRfcG91bHRyeSIgPSAiZnJlc2ggbWVhdCIsICJub25mcmllZF9yb290c190dWJlcnNfcGxudG5fcG90cyIgPSAibm9uIGZyaWVkIHJvb3QgdmVnLiIsICJmcmllZF9yb290c190dWJlcnNfcGxudG5fcG90cyIgPSAiZnJpZWQgcm9vdCB2ZWcuIiwgImdyYWluX2NlcmVhbCIgPSAiZ3JhaW4vY2VyZWFsIiwgImxlZ3VtZXNfcHVsc2VzIiA9ICJsZWd1bWVzIiwgIm1vZGVybl9taXhlZF9kaXNoZXMiID0gIm0uZGlzaCIsICJudXRzX3NlZWRzIj0gIm51dHMvc2VlZHMiLCAicHJvY3NzZF9mcmllZF9maXNoIiA9ICJwcm9jZXNzZWQgZmlzaCIsICJwcm9jc3NkX2ZyaWVkX21lYXRfcG91bHRyeSIgPSAicHJvY2Vzc2VkIG1lYXQiLCAic2F2b3VyeV9zbmFja3NfcGllcyIgPSAic2F2b3VyeSBzbmFja3MiLCAic29kYXNfc3dlZXRlbmVkX2JldnMiID0gInN3ZWV0ZW5lZCBkcmlua3MiLCAic291cHNfc3Rld3MiPSAic291cHMvc3Rld3MiLCAic3VnYXJfc3dlZXRfc3ByZWFkcyIgPSAic3dlZXRlbmVkIHNwcmVhZHMiLCAidGVhX2NvZmZlZSIgPSAidGVhL2NvZmZlZSIsICJ0cmFkX21peGVkX2Rpc2hlcyIgPSAidHJhZC4gZGlzaGVzIiwgInZlZ2V0YWJsZXMiID0gInZlZy4iLCAiZmVzaF9qdWljZXMiID0gImZyZXNoIGp1aWNlIikpCmhvX2xjYTNfbm9sZWcgPC0gaG9fbGNhMyArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgIyBQbG90IHdpdGhvdXQgbGVnZW5kCgojIFBsb3QgYnV0IGhhdmUgbmFtZXMgb3ZlcmxhcApndF8zIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKGhvX2xjYTMpKSAjIFdpdGggbGVnZW5kCmd0XzMkbGF5b3V0JGNsaXBbZ3RfMyRsYXlvdXQkbmFtZSA9PSAicGFuZWwiXSA8LSAib2ZmIgpnZ3NhdmUoIi4vUGxvdHMvbGNhX2Zvb2RfYWR2X2hvLnRpZmYiLCBwbG90ID0gZ3RfMywgc2NhbGUgPSAxLCBkcGkgPSAzMDApCmdnc2F2ZSgiLi9QbG90cyBsb3cgcmVzL2xjYV9mb29kX2Fkdl9oby5qcGVnIiwgcGxvdCA9IGd0XzMsIGRwaSA9IDMwMCwgc2NhbGUgPSAxKQpwbG90KGd0XzMpCgpndF8zX25sIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKGhvX2xjYTNfbm9sZWcpKSAjIFdpdGhvdXQgbGVnZW5kCmd0XzNfbmwkbGF5b3V0JGNsaXBbZ3RfM19ubCRsYXlvdXQkbmFtZSA9PSAicGFuZWwiXSA8LSAib2ZmIgpnZ3NhdmUoIi4vUGxvdHMvbGNhX2Zvb2RfYWR2X2hvX25vbGVnLnRpZmYiLCBwbG90ID0gZ3RfM19ubCwgc2NhbGUgPSAxLCBkcGkgPSAzMDApCmdnc2F2ZSgiLi9QbG90cyBsb3cgcmVzL2xjYV9mb29kX2Fkdl9ob19ub2xlZy5qcGVnIiwgcGxvdCA9IGd0XzNfbmwsIGRwaSA9IDMwMCwgc2NhbGUgPSAxKQoKYGBgCgpKb2luIGFsbCBwbG90cyB0b2dldGhlciBpbnRvIGEgc2luZ2xlIG9uZS4KCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoZ3JpZEV4dHJhKQojIENyZWF0ZSBibGFuayBwbG90IHRvIGNlbnRyZSBsZWdlbmQKYmxhbmtQbG90IDwtIGdncGxvdCgpK2dlb21fYmxhbmsoYWVzKDEsMSkpICsgCiAgY293cGxvdDo6dGhlbWVfbm90aGluZygpCgojIEpvaW4gdG9nZXRoZXIgcGxvdHMgaW50byBzaW5nbGUgcGxvdAojIFNhdmUgYXMgUERGCnBkZigiLi9QbG90cy9ob19hbGxfcGxvdHMucGRmIiwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gMTApIApncmlkLmFycmFuZ2UoZ3RfMV9ubCwgZ3RfMV9ubGEsIGd0XzJfbmwsIGd0XzNfbmwsIGxlZ2VuZCwgbmNvbCA9IDIsIG5yb3cgPSAzLAogICAgICAgICAgICAgICAgICAgICAgd2lkdGhzID0gYygxMCwgMTApLCBoZWlnaHRzID0gYygxMCwgMTAsIDQpKQpkZXYub2ZmKCkKCiMgU2F2ZSBhcyBpbWFnZS90aWZmIGZpbGUKdGlmZigiLi9QbG90cy9ob19hbGxfcGxvdHMudGlmZiIsIHdpZHRoID0gMTAsIGhlaWdodCA9IDEwLCB1bml0cyA9ICJpbiIsIHJlcyA9IDMwMCkKZ3JpZC5hcnJhbmdlKGd0XzFfbmwsIGd0XzFfbmxhLCBndF8yX25sLCBndF8zX25sLCBsZWdlbmQsIG5jb2wgPSAyLCBucm93ID0gMywKICAgICAgICAgICAgICAgICAgICAgIHdpZHRocyA9IGMoMTAsIDEwKSwgaGVpZ2h0cyA9IGMoMTAsIDEwLCA0KSkKZGV2Lm9mZigpCgpgYGA=